Utopia Tech
Engineering4 min read

Origin Range Requests: Serving large files without range-request tuning

A video player seeking to the middle of a movie asks for a few megabytes. Under our old range caching, that one request could make Cloudflare pull 128 MiB from the origin and move it between data centers, sometimes after the viewer had already left. Range requests are how large files get delivered, and caching them naively easily leads to wasted network bandwidth and wasted dis

UT

Utopia Tech

October 23, 2026 · 4 min read

Share

A video player seeking to the middle of a movie asks for a few megabytes. Under our old range caching, that one request could make Cloudflare pull 128 MiB from the origin and move it between data centers, sometimes after the viewer had already left. Range requests are how large files get delivered, and caching them naively easily leads to wasted network bandwidth and wasted disk operations when running a CDN at scale.

So we rebuilt how our cache handles them. For R2, Cloudflare's object storage, p99 time to first byte dropped by about half, and a follow-up improvement cut tiered cache traffic for R2 and similar workloads by about 6%. Today, we're making that new implementation available as Origin Range Requests , a self-service feature on all plans.

There's no range size to tune and no need to contact support. Turn it on with a Cache Rule , and Cloudflare handles the rest. A request for part of a file An HTTP range request asks for part of a resource instead of the whole resource.

The client sends a normal GET with a Range header: GET /movie. mp4 HTTP/1. 1 Host: example.

com Range: bytes=1048576-2097151 If the server supports the request, it returns 206 Partial Content and identifies the returned bytes with Content-Range : HTTP/1. 1 206 Partial Content Content-Range: bytes 1048576-2097151/524288000 Content-Length: 1048576 Range requests are common for large objects. A video player can request bytes around a seek position instead of the whole file.

A download manager can resume after an interruption. A package manager can fetch part of an artifact. A client can inspect the end of a file without downloading everything before it.

The client decides whether to request a range, and Cloudflare does not change that request. Instead, Origin Range Requests changes how Cloudflare satisfies it. The range-size problem Cloudflare has supported range-request caching for years via static zone configuration.

The previous implementation resembled the cache-slicing described in an nginx blog post : each client request was mapped to fixed-size ranges of the file, with the range size and file extensions configured per zone. The size of each range created a tradeoff: small ranges led to many small origin requests and memory pressure on Cloudflare from coalescing all of the requests in-memory, while large ranges caused Cloudflare to download much more data than the client requested.

Updates to the range size itself would invalidate cache entries, since the size was part of the cache key. This design also meant people requesting content through our network could have unpleasant experiences accessing these files. Concurrent requests that fell inside the same range, no matter how far apart each client’s requested range was, could block each other.

Our nginx-based cache also couldn’t combine range caching with concurrent streaming , a feature we built to let multiple clients read a file from cache while it's still being written. Turning both on together cut responses short, so each range had to be fully downloaded before anyone could read it, and popular files needed a separate origin fetch for every range.

The extra bytes could also cross several parts of our distributed cache: from the origin to one data center, between cache tiers, and then toward the client. Every hop multiplied the waste. No value works equally well for a small seek, a sequential download, a large media file, and every origin and cache topology.

Our internal cache limitations were directly exposed to customers, who should not need to understand our capabilities in-depth to have files served efficiently. Fortunately, our transition from nginx to a Pingora -based caching server created an opportunity to address the implementation problems that had forced a hard-to-use setting onto customers. Fixed-size cache chunks The fix came from something Pingora was already doing.

To make it easy to resume interrupted downloads, it stores every cached file on disk in fixed-size chunks. If the cache already thinks in chunks, the range size doesn't need to be a setting at all, it can just be the chunk! For a range request, Cloudflare checks which requested bytes are already cached.

It serves those bytes directly. For missing bytes, it fetches origin ranges aligned to the cache's fixed-sized-chunk boundaries, stores the result in the same chunks used for ordinary cache storage, and returns only the bytes requested by the client. For example, a request for bytes 150-250 can cause Cloudflare to fetch the aligned chunk containing those bytes.

The downstream response still contains only 150-250 . This does not eliminate extra work for requests smaller than our chunk size — such a request can still require fetching the whole chunk containing it. We also are taking on the cost of more work for non-aligned ranges.

The difference is that the extra work is bounded and predictable, and no longer determined by a customer-selected range size that can cause unpredictable effects on us and origins. Coordinating cached and in-flight data Parsing the Range header is straightforward. The harder problem is producing one correct response when the requested bytes are split across cached data, an origin response, and downloads already in progress.

At a high level, the edge: Looks up the asset headers and range-coverage metadata. Reads whatever part of the asset it can from disk or streaming in memory. Fetches missing coverage from the origin using aligned ranges.

Writes the new bytes and records the completed range in metadata. Combines the pieces and sets Content-Range and Content-Length for the client response. This is a coordinator, not a single cache lookup.

One request can use a cached prefix, an in-flight download, and a newly fetched suffix. The internal origin response can be larger than the downstream response, but the downstream status and headers describe only the requested range.

Originally published at blog.cloudflare.com

Share
▸ Want a deeper look?

Talk to an architect about applying this to your stack.

60-minute technical evaluation, no obligation. We'll map the ideas in this article to your environment.

Skip to main content