Cloudflare Origin Range Requests Serve Large Files From Cache Chunks

Cloudflare rebuilt range caching around the fixed-size chunks Pingora already writes to disk, removed the per-zone range-size setting, halved R2 p99 time to first byte and cut tiered cache t

Netics editorial card on Cloudflare Origin Range Requests, showing a range request answered from fixed-size cache chunks.
Netics editorial card on Cloudflare Origin Range Requests, covering the Range header, the fixed-size chunks Pingora writes, the coordinator that composes cached and in-flight bytes, and the R2 measurements.

TL;DR

  • A range request is an HTTP GET carrying a Range header that asks for part of a resource, and a server that honours it answers 206 Partial Content with the bytes named in Content-Range.
  • Cloudflare's previous range cache mapped each request onto fixed-size file ranges configured per zone, and the range size sat inside the cache key.
  • Pingora already writes every cached file to disk in fixed-size chunks, so the chunk boundary became the range size and the per-zone setting disappeared.
  • A coordinator combines cached bytes, bytes from a download already in flight and bytes fetched fresh from the origin into one response.
  • Composed responses are validated against the entity tag, the total asset size and the If-Range header, and an unsafe case returns the full representation.
  • R2 measured p99 time to first byte roughly halved across its storage regions, and tiered cache traffic for R2 and similar workloads fell about 6% week over week.
  • Cache Rules enable the feature through origin_range_requests, cache eligibility stays unchanged and the origin has to support byte ranges for partial fetches to help.
Cloudflare Origin Range Requests blog post, opening section
Capture of the Cloudflare post, blog.cloudflare.com/origin-range-requests, taken 29 October 2026.

A video player seeking into the middle of a movie asks for a few megabytes. Under Cloudflare's previous cache, that request could make the edge pull 128 MiB from the origin and move it between data centers, sometimes after the viewer had already left. The client had asked for only a few megabytes. The size of the block the cache fetched on its behalf was the problem, and that size was a customer setting.

On 23 October 2026 Cloudflare made the rebuilt implementation available as Origin Range Requests, a self-service feature on all plans. Operators turn it on with a Cache Rule, while the edge chooses the chunk boundaries automatically. The interesting part is the argument that a tuning knob can be removed once the storage layer underneath supplies the same number.

A Range header asks for part of a file and gets 206 Partial Content

An HTTP range request asks for a selected byte interval within a resource. The client sends a normal GET with a Range header naming the byte interval, and a server that supports the request returns 206 Partial Content with a Content-Range header identifying the bytes it returned and their total. Video players use it around a seek position, download managers use it to resume, package managers use it to fetch part of an artifact, and a client can request and inspect bytes at the end of a file.

Netics definition card for the Range request header and the 206 Partial Content reply
Netics editorial visual: the request shape the whole feature exists to answer, and the status a compliant server returns.

The client chooses whether to send a range request, which Cloudflare forwards unchanged. The rebuilt edge satisfies that request through the cache internals described in most of Cloudflare's post.

Fixed-size ranges made the range size a per-zone setting and a cache-key component

The old implementation resembled the cache-slicing approach described in an nginx blog post: each client request was mapped onto fixed-size ranges of the file, with the range size and the file extensions configured per zone. That design carried a trade-off the customer had to resolve. Small ranges produced many small origin requests and memory pressure from coalescing them in memory. Large ranges pulled far more data than the client asked for. Worse, the range size was part of the cache key, so changing it invalidated cache entries.

Two consequences followed. Concurrent requests falling inside the same range blocked each other however far apart their actual bytes were, and range caching could not run alongside concurrent streaming, the feature that lets several clients read a file from cache while it is still being written. Popular files needed a separate origin fetch for every range. Configured sizes on the old system ran from tens of kilobytes to tens of gigabytes, and both extremes caused real incidents inside Cloudflare.

Cloudflare diagram of the range coordinator combining cached and upstream bytes
Cloudflare's diagram from the post, blog.cloudflare.com/origin-range-requests: the same client request served from cached bytes combined with a ranged upstream fetch, with Content-Range and Content-Length describing only the requested bytes.

Pingora already writes cached files in fixed-size chunks

The fix came from something Pingora, Cloudflare's replacement for its nginx-based cache server, was already doing to make downloads resumable: it stores every cached file on disk in fixed-size chunks. Because the cache already thinks in chunks, Cloudflare uses the chunk as the range size.

The behaviour then follows. For a range request Cloudflare checks which of the requested bytes are cached and serves those directly. For missing bytes it fetches origin ranges aligned to the chunk boundaries, stores the result in the same chunks used for ordinary cache storage, and returns only the bytes the client requested. A request for bytes 150-250 can cause a fetch of the aligned chunk containing them, and the downstream response still carries 150-250. A request smaller than one chunk can pull that whole chunk, and non-aligned ranges add work whose cost remains bounded and predictable.

Netics stat callout on the R2 p99 time to first byte reduction
Netics editorial visual: the headline number from Cloudflare's own R2 migration, with the measurement it applies to.

A coordinator composes cached, in-flight and freshly fetched bytes

Parsing the header is easy. Producing one correct response when the requested bytes are split across cached data, an origin response and downloads already in progress is the hard part, and the post describes a coordinator that combines those sources.

The edge looks up the asset headers and the range-coverage metadata, reads what it can from disk or from a stream in memory, fetches missing coverage from the origin with aligned ranges, writes the new bytes and records the completed range in metadata, then combines the pieces and sets Content-Range and Content-Length for the client. One request can use a cached prefix, an in-flight download and a newly fetched suffix together, and if a download already covers another request's bytes the second request attaches to it. The internal origin response can be larger than the downstream response. The downstream status and headers describe only the requested range.

Netics before-and-after visual on fixed-size ranges and chunk-aligned fetches
Netics editorial visual: what changed in the data path, from a per-zone range size inside the cache key to the chunk boundaries Pingora already writes.

Composed responses are validated against the entity tag and the asset size

A composed response is legitimate only when every byte belongs to the same representation, so the coordinator checks that each origin response matches the requested range, that the total asset size is stable, and that the entity tag stays consistent across subrequests. The If-Range header lets a client ask for a range only if the representation still matches a known validator; a validator mismatch makes Cloudflare return the full representation, keeping the response tied to one version.

Cloudflare also refuses to compose ranges for a representation it is about to decompress, because a range over compressed bytes selects different bytes than the same range over the decompressed response. Cloudflare handles those cases by serving the transformed full response directly. The visible behaviour is ordinary HTTP: 206 with an accurate Content-Range when the range is satisfiable, 416 Range Not Satisfiable when it is not, and the complete representation when a ranged response cannot be produced safely.

R2 measured p99 time to first byte halved and 6% less tiered cache traffic

Cloudflare moved existing users of the old feature onto the new implementation before opening it to everyone, starting with the workloads that hurt most: many concurrent range requests against very large files on spiky traffic. R2 was the largest internal user, with a configured range size of 64 MiB, which meant a small read crossing a range boundary could cost 128 MiB of transfer between data centers.

Cloudflare Cache documentation landing page listing Cache Rules
Capture of the Cloudflare Cache documentation, developers.cloudflare.com/cache, taken 29 October 2026.

Cloudflare reports two encouraging measurements whose scope remains difficult to assess independently. For the p99 result, the post provides no absolute TTFB values, sample counts, observation window or regional breakdown. The 6% figure compares one week with the previous week for R2 and similar workloads, without traffic-normalized data or a control, leaving workload mix and weekly demand as possible contributors. Both figures cover Cloudflare's own R2 rollout; effects for another origin, object mix or cache topology remain unmeasured. Across R2's storage regions, p99 time to first byte dropped by roughly half on both cache hits and misses. A follow-up change let the coordinator combine bytes already on disk with bytes fetched upstream in a single response. Cloudflare then measured tiered cache traffic for R2 and similar workloads falling about 6% week over week, equivalent to petabytes less data moving between data centers every day.

Cache Rules enable the feature and the origin keeps the last word

Configuration is one rule. Match the large-file traffic in Cache Rules and set Origin Range Requests to On, in the dashboard under Caching and Cache Rules or through the API with origin_range_requests: {"mode": "on"}. Cloudflare intends to make this the default way certain file types are served, modifiable by cache rules.

Two limits matter. The feature leaves cache eligibility alone, so cacheability continues to follow the existing eligibility rules, and a partial origin fetch only helps when the origin supports byte ranges itself. The traffic that gains is the traffic that already asks for parts of a large cacheable object: progressive MP4 video, resumable downloads, package repositories and software distributions, disk images and archives, and AI training or inference jobs that fetch whole model files or selected regions of a model artifact.

Netics warning box on the two conditions range requests leave with the origin
Netics editorial visual: the two conditions the feature leaves in place, cache eligibility and origin support for byte ranges.

Pingora's existing chunk boundaries now supply the former per-zone setting's value directly and support the coordinator's correctness model. It closes with an honest limit, since the client still chooses whether to send a Range header and the origin still has to answer it. For related Cloudflare coverage, see Cloudflare Hyperdrive's canonical query-result cache. Teams planning a large-file delivery tier can review it with Netics, and book a consultation once the traffic profile is known.

Sources

Source: the Cloudflare blog post of 2026-10-23 and the Cloudflare Cache documentation landing page, read on 2026-10-29. The old per-zone range size and its place in the cache key, the nginx cache-slicing comparison, the blocked concurrent requests, the 64 MiB R2 configuration and the 128 MiB inter-datacenter cost, the chunk-aligned fetch behaviour, the coordinator steps, the If-Range and entity-tag validation rules, the 206 and 416 outcomes, the halved p99 time to first byte, the 6% tiered cache reduction and the origin_range_requests configuration key all come from those pages.