HomeJournalThis post

Build resumable downloads with HTTP Range

Safe resume binds partial bytes to a strong validator, validates Content-Range, treats full responses as restart, reconciles 416, and publishes atomically.

JP
JP Casabianca
Designer/Engineer · Bogotá

A saved byte offset is not enough to resume a download.

If the file at the URL changed while the client was offline, appending byte 40,000,001 from the new representation to the first 40,000,000 bytes of the old one creates an artifact the server never served. It can have the expected length and still be corrupt.

RFC 9110 range requests define Range, Content-Range, 206 Partial Content, 416, and If-Range. If-Range lets a client request the remaining range only when the selected representation still matches a validator; otherwise the server sends the complete representation. That branch is the safety mechanism, not a nuisance response.

I would persist a small manifest beside an unpublished partial file: URL, effective resource identity, strong ETag where available, total length, completed interval, digest state if used, and last response evidence. Resume is permitted only when the server response proves continuity.

The completed filename appears only after length, validator, and integrity checks pass and the temporary file is atomically promoted.

01 · PersistRecord bytes and identity

Write to a temporary file, fsync according to consequence, and checkpoint contiguous length, strong ETag, total size, URL, and digest state.

02 · RequestAsk for the remainder conditionally

Send Range bytes=N- with If-Range using the stored strong validator; treat redirects and authorization scope deliberately.

03 · VerifyAppend, restart, or finish

Accept only coherent 206 metadata, restart from a full 200 or mismatch, handle 416 by revalidation, and publish after terminal integrity checks.

Figure 1: Resume is a representation-validation protocol.

Define the resource identity

Resume scope should include effective URL rules, authenticated principal or tenant, selected representation, content coding, and an application artifact identity where available.

I would pressure-test that decision with four questions:

  • What exactly is being downloaded?
  • Can redirects change authority?
  • Does compression change byte positions?
  • Is a signed digest available?

The failure mode here is treating any response from the same path as the same bytes. In browser, desktop, mobile, and service clients downloading large exports, media, models, archives, and artifacts over unreliable networks where the underlying representation can change between attempts, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a download resource-identity record. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is resume rejected when representation scope or authority changes. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put a download resource-identity record beside the question “What exactly is being downloaded?” before the first implementation review. The next pass would use “Can redirects change authority?” to test the boundary, then “Does compression change byte positions?” to expose the state most likely to be missed. I would keep “Is a signed digest available?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports resume rejected when representation scope or authority changes.

Discover range behavior carefully

Servers can advertise Accept-Ranges, answer a small probe, ignore ranges, or vary behavior by object and proxy, so capability should be learned from actual responses without wasting the full transfer.

The practical review starts here:

  • Does this resource honor Range?
  • Is HEAD metadata trustworthy?
  • Would a one-byte probe help?
  • Can the CDN transform responses?

Those questions keep assuming Accept-Ranges alone guarantees every later response from becoming the default. I would capture the decision in a range-capability probe policy, then use it while the work is still cheap to change. For large downloads that recover bandwidth without stitching bytes from different representations, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like server and intermediary fixtures selecting the documented fresh or resume path. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make a range-capability probe policy part of the working surface. I would use it to answer “Does this resource honor Range?” while scope is still flexible, and “Is HEAD metadata trustworthy?” before code or content becomes expensive to unwind. During QA, “Would a one-byte probe help?” and “Can the CDN transform responses?” become concrete checks rather than discussion prompts. That sequence turns large downloads that recover bandwidth without stitching bytes from different representations into something the team can operate and gives me a specific outcome to report: server and intermediary fixtures selecting the documented fresh or resume path.

  1. 206Validate and append

    Content-Range start equals local length, end and total are coherent, validator remains acceptable, and body byte count matches the declared interval.

  2. 200Representation must restart

    If-Range did not match or ranges were ignored; truncate a new temporary generation and consume the complete response from byte zero.

  3. 416Reconcile local and remote length

    Inspect unsatisfied Content-Range total where supplied; complete only after validator and exact-length proof, otherwise discard or restart.

Figure 2: Response status determines the safe next state.

Require representation continuity

Store a strong ETag when provided and send it through If-Range; if identity cannot be proven strongly enough for the artifact's consequence, restart or verify against an independent content digest.

Before implementation, I would answer:

  • Is the ETag strong?
  • Can Last-Modified collide?
  • Does an application digest exist?
  • What risk is acceptable without a validator?

The artifact is a validator-confidence table. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is sending Range without binding it to the representation already on disk; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.

For me, the useful receipt is changed-resource fixtures never producing a mixed published file. That connects a download state machine that discovers byte-range support, pins representation identity with a strong validator, writes verified offsets to temporary storage, resumes with Range and If-Range, validates Content-Range, restarts safely on mismatch, and atomically publishes only a complete artifact to an observable result instead of a process claim.

I would test this with one typical case and one boundary case. The typical case should make “Is the ETag strong?” easy to answer. The boundary should force a decision about “Can Last-Modified collide?” and “Does an application digest exist?.” I would record both in a validator-confidence table, including the part that stayed unresolved after the first pass. The final check, “What risk is acceptable without a validator?,” is where the artifact earns its place: it either supports changed-resource fixtures never producing a mixed published file, or it shows exactly why another iteration is needed.

Persist a crash-safe manifest

The manifest should name generation, validator, total, contiguous durable offset, temporary path, hash state, and response history, and it must never claim bytes beyond what storage made durable.

I would use these prompts during the working review:

  • Which bytes survived a crash?
  • Is the manifest update atomic?
  • Can temp and metadata diverge?
  • How are old generations cleaned?

If the team slips into updating the saved offset before the file data is safely written, the product can still look complete while its operating rule stays ambiguous. I would make a partial-download manifest schema the shared reference and keep it small enough to update as evidence changes.

The standard is power-loss tests resuming from a verified conservative boundary. That tells me whether the decision helped the product, not merely whether the document was completed.

The working sequence is small: draft a partial-download manifest schema, review it against “Which bytes survived a crash?,” implement the narrowest useful path, and then return with evidence for “Is the manifest update atomic?.” I would use “Can temp and metadata diverge?” to inspect product consequence and “How are old generations cleaned?” to decide whether the result is stable enough to ship. This keeps updating the saved offset before the file data is safely written visible as a known risk and makes power-loss tests resuming from a verified conservative boundary the release receipt rather than a hopeful conclusion.

SignalDecisionWorking note
Strong ETagPreferred representation identityUse in If-Range exactly as received; do not weaken or reinterpret it across content codings or transformed URLs.
Last-ModifiedAllowed but coarseIf used under RFC rules, understand timestamp granularity and change risk; higher-consequence artifacts may require restart or digest verification.
No validatorOptimization lacks continuity proofA range may save bytes but cannot safely assert the representation is unchanged; prefer a fresh full download unless an application digest identifies content.
Figure 3: Validators carry different resume confidence.

Request one coherent interval

For a contiguous partial file, request bytes=N- with If-Range, preserve authorization and cancellation, bound retries, and avoid multi-range complexity until a measured need justifies it.

I would pressure-test that decision with four questions:

  • What is the first missing byte?
  • Which validator accompanies it?
  • Can authorization expire?
  • Does parallel range add value?

The failure mode here is launching many parallel intervals without a durable gap map or validator discipline. In browser, desktop, mobile, and service clients downloading large exports, media, models, archives, and artifacts over unreliable networks where the underlying representation can change between attempts, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a resume request builder. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is wire captures showing the exact conditional range intended. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put a resume request builder beside the question “What is the first missing byte?” before the first implementation review. The next pass would use “Which validator accompanies it?” to test the boundary, then “Can authorization expire?” to expose the state most likely to be missed. I would keep “Does parallel range add value?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports wire captures showing the exact conditional range intended.

Validate every 206

Parse Content-Range strictly, require start to equal local length, end and total to be coherent, compare known total, count received bytes, and reject multipart or encoded surprises outside the contract.

The practical review starts here:

  • Does the range start match?
  • Is total unchanged?
  • Did body length equal the interval?
  • Was content encoding stable?

Those questions keep appending any body returned with status 206 from becoming the default. I would capture the decision in a strict Content-Range validator, then use it while the work is still cheap to change. For large downloads that recover bandwidth without stitching bytes from different representations, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like malformed and inconsistent range fixtures failing before file mutation. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make a strict Content-Range validator part of the working surface. I would use it to answer “Does the range start match?” while scope is still flexible, and “Is total unchanged?” before code or content becomes expensive to unwind. During QA, “Did body length equal the interval?” and “Was content encoding stable?” become concrete checks rather than discussion prompts. That sequence turns large downloads that recover bandwidth without stitching bytes from different representations into something the team can operate and gives me a specific outcome to report: malformed and inconsistent range fixtures failing before file mutation.

Treat 200 as a safe restart

A full response to an If-Range request means the condition failed or range was not applied; create or truncate a new generation and process it from byte zero rather than appending.

Before implementation, I would answer:

  • Why did the server send 200?
  • Is the old temp retained for diagnosis?
  • Can disk hold a new generation?
  • How is progress reset honestly?

The artifact is a representation-restart transition. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is appending a 200 body after the partial bytes; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.

For me, the useful receipt is validator-change tests restarting without exposing mixed progress as completion. That connects a download state machine that discovers byte-range support, pins representation identity with a strong validator, writes verified offsets to temporary storage, resumes with Range and If-Range, validates Content-Range, restarts safely on mismatch, and atomically publishes only a complete artifact to an observable result instead of a process claim.

I would test this with one typical case and one boundary case. The typical case should make “Why did the server send 200?” easy to answer. The boundary should force a decision about “Is the old temp retained for diagnosis?” and “Can disk hold a new generation?.” I would record both in a representation-restart transition, including the part that stayed unresolved after the first pass. The final check, “How is progress reset honestly?,” is where the artifact earns its place: it either supports validator-change tests restarting without exposing mixed progress as completion, or it shows exactly why another iteration is needed.

Reconcile 416

Range Not Satisfiable can mean the local file is already complete, the remote object shrank, or metadata drifted; inspect total and validator, verify exact length and digest, then finish or restart deliberately.

I would use these prompts during the working review:

  • What total did the server report?
  • Does validator still match?
  • Is local length exact?
  • Can integrity prove completion?

If the team slips into renaming the partial file complete whenever the server rejects the range, the product can still look complete while its operating rule stays ambiguous. I would make a 416 recovery decision table the shared reference and keep it small enough to update as evidence changes.

The standard is oversized, exact, and changed-object fixtures reaching distinct safe outcomes. That tells me whether the decision helped the product, not merely whether the document was completed.

The working sequence is small: draft a 416 recovery decision table, review it against “What total did the server report?,” implement the narrowest useful path, and then return with evidence for “Does validator still match?.” I would use “Is local length exact?” to inspect product consequence and “Can integrity prove completion?” to decide whether the result is stable enough to ship. This keeps renaming the partial file complete whenever the server rejects the range visible as a known risk and makes oversized, exact, and changed-object fixtures reaching distinct safe outcomes the release receipt rather than a hopeful conclusion.

Publish atomically

Check final total and digest, flush file and metadata as required, set permissions, move within one filesystem atomically, and make completion idempotent so readers never observe a partial artifact at the final path.

I would pressure-test that decision with four questions:

  • Which checks gate publish?
  • Is rename atomic here?
  • Can another process consume early?
  • What if completion repeats?

The failure mode here is downloading directly into the filename other components watch. In browser, desktop, mobile, and service clients downloading large exports, media, models, archives, and artifacts over unreliable networks where the underlying representation can change between attempts, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be an atomic completion protocol. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is readers observing either no artifact or one fully verified artifact. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put an atomic completion protocol beside the question “Which checks gate publish?” before the first implementation review. The next pass would use “Is rename atomic here?” to test the boundary, then “Can another process consume early?” to expose the state most likely to be missed. I would keep “What if completion repeats?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports readers observing either no artifact or one fully verified artifact.

Exercise unreliable reality

Tests should disconnect at every boundary, change ETag and length, ignore Range, return malformed Content-Range, compress unexpectedly, expire auth, exhaust disk, crash between fsyncs, cancel, and repeat completion.

The practical review starts here:

  • Can mixed bytes publish?
  • Can progress exceed durable data?
  • Does cancellation preserve resumable state?
  • Are temporary generations reclaimed?

Those questions keep testing pause and resume against one static local server from becoming the default. I would capture the decision in a resumable-download fault suite, then use it while the work is still cheap to change. For large downloads that recover bandwidth without stitching bytes from different representations, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like verified completion or explicit restart across protocol, storage, and lifecycle failures. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make a resumable-download fault suite part of the working surface. I would use it to answer “Can mixed bytes publish?” while scope is still flexible, and “Can progress exceed durable data?” before code or content becomes expensive to unwind. During QA, “Does cancellation preserve resumable state?” and “Are temporary generations reclaimed?” become concrete checks rather than discussion prompts. That sequence turns large downloads that recover bandwidth without stitching bytes from different representations into something the team can operate and gives me a specific outcome to report: verified completion or explicit restart across protocol, storage, and lifecycle failures.

What I would show in the work

The public version needs evidence from the work itself. For this topic, the first five artifacts I would reach for are:

  • a download resource-identity record
  • a range-capability probe policy
  • a validator-confidence table
  • a partial-download manifest schema
  • a resume request builder

I would not publish all five at equal weight. One should orient the reader, one should reveal the hardest tradeoff, and one should prove the result. The others can live in a downloadable note or appear as supporting frames. That edit matters because a download state machine that discovers byte-range support, pins representation identity with a strong validator, writes verified offsets to temporary storage, resumes with Range and If-Range, validates Content-Range, restarts safely on mismatch, and atomically publishes only a complete artifact becomes harder to understand when every process detail is treated as equally important.

I would also show one rejected direction. The useful version is specific: which option looked attractive, which constraint made it wrong, and what evidence supported the narrower choice. That gives an engineering manager something real to question and keeps the case study from reading like the final answer was obvious from the beginning.

download-manifest.json
# resource
https://…/export.zip / ETag "a81"
Effective URL approved, total 4,801,992,110 bytes, content encoding identity, expected sha256 from signed metadata.

# partial generation g_4 / contiguous 1,442,119,680 Temp path download.part, last fsync offset 1,440,000,000, retry 3, validator strong, no sparse gaps.

# complete 206 1442119680-4801992109/4801992110 Body length exact, final digest pass, metadata fsynced, atomic rename to export.zip, manifest removed, completion receipt retained.

Figure 4: The manifest makes a partial file non-authoritative.

Resource path

The practical follow-up I would build is a resumable-download implementation kit with TypeScript state machine, HEAD and probe strategy, strong-validator rules, Range and If-Range requests, 206 and 200 handling, Content-Range parser, temporary-file manifest, incremental digest option, disk-space checks, cancellation, retry backoff, restart policy, atomic rename, telemetry, server fixtures, and corruption tests. I am treating that as a resource backlog item, not pretending the adjacent downloads below are the same artifact. The related cards cover useful pieces of the workflow today; this specific file should only be published when its examples, fields, and instructions are complete.

The first version should stay concise: context, constraint, decision, evidence, owner, and follow-up. Its value would come from helping someone repeat this exact review, not from adding another generic PDF to the site.

Review checklist

The article-specific review questions are:

  • What exactly is being downloaded?
  • Does this resource honor Range?
  • Is the ETag strong?
  • Which bytes survived a crash?
  • What is the first missing byte?
  • Does the range start match?
  • Why did the server send 200?
  • What total did the server report?
  • Which checks gate publish?
  • Can mixed bytes publish?

I would add two editorial checks before publishing: can a recruiter find the point in the first minute, and can an engineer trace at least one claim to an implementation or production receipt? If either answer is no, the article needs another edit.

Implementation notes

For large downloads that recover bandwidth without stitching bytes from different representations, I would write the implementation note before polish. It would name the changed surface, source of truth, owner, failure boundary, and verification path. Those details prevent the principle from floating above the actual code or operational workflow.

The proof signals I care about are specific to this article:

  • malformed and inconsistent range fixtures failing before file mutation
  • validator-change tests restarting without exposing mixed progress as completion
  • oversized, exact, and changed-object fixtures reaching distinct safe outcomes
  • readers observing either no artifact or one fully verified artifact
  • verified completion or explicit restart across protocol, storage, and lifecycle failures

I would choose two or three of those signals for the first release rather than instrumenting everything. The strongest pair usually combines one direct behavior check with one operating check: a route and a data query, a keyboard path and a support state, a handler replay and a reconciliation result, or a migration count and a rendered screen.

The follow-up belongs in the note before shipping. It should say what remains temporary, what evidence would trigger another pass, and who owns that decision. That is how the first version stays intentionally narrow without making the boundary invisible.

Case-study packaging

I would structure the case-study version around the four visual lessons already established:

  • Resume is a representation-validation protocol.
  • Response status determines the safe next state.
  • Validators carry different resume confidence.
  • The manifest makes a partial file non-authoritative.

The opening frame explains the product pressure. The middle two show the decision moving through the system. The last frame is the receipt: what was checked, what held, and what remained unresolved. That order lets the reader move from product judgment into implementation detail without reconstructing the whole project first.

I would include one caveat tied to browser, desktop, mobile, and service clients downloading large exports, media, models, archives, and artifacts over unreliable networks where the underlying representation can change between attempts: a data limit, rollout boundary, unsupported state, external dependency, or result that is still directional. A precise caveat makes the evidence easier to trust because it shows where the claim stops.

The final test is whether the page creates a better conversation. If the artifact helps someone ask a sharper question about product judgment, implementation detail, or release proof in a live interview, it belongs in the story.

Interview angle

In an interview, I would explain this through a download state machine that discovers byte-range support, pins representation identity with a strong validator, writes verified offsets to temporary storage, resumes with Range and If-Range, validates Content-Range, restarts safely on mismatch, and atomically publishes only a complete artifact. The story should start with the product pressure, then move into the system constraint, the artifact, and the proof. That order keeps the answer grounded. It also gives the interviewer several places to go deeper: data, frontend architecture, design systems, support, migration, accessibility, or release process.

The strongest version of the answer includes a tradeoff. I want to be able to say what I chose, what I left alone, and how I knew the work helped. That is more credible than presenting every project as a clean win.

The hiring signal

A validator-aware resumable downloader is a hiring signal because it shows I can connect HTTP representation semantics, storage durability, integrity, recovery UX, cancellation, and adversarial protocol testing.

That is the level I want this site to communicate. The work should show taste, but it should also show operating judgment. It should make me look like someone who can enter a real product system, understand the messy middle, ship the useful version, and leave enough proof for the next person to trust it.

Companion artifacts

Use this after reading.

Practical downloads and templates that turn the article into something you can bring into a product review, implementation pass, or agent workflow.

RepoJun 2026

Agent-Ready API Spec Template

An OpenAPI and Postman starter template for APIs that AI agents can discover, call, and recover from safely.

OpenAPIPostmanAI agents
View details
TemplateJul 2026

Dependency Adoption Receipt

A reviewable receipt for package need, identity, provenance, permissions, supply-chain risk, verification, ownership, and removal.

Supply chainSecurityAI-assisted
View details
DownloadJun 2026

Front-End State Recipes

Reusable recipes for optimistic actions, loading, empty, error, data-transition, and disabled-control states.

FrontendStatesUX
View details