Cache HTTP Range (206 Partial Content) responses at the Cloudflare edge — without an Enterprise plan.
A tiny, dependency-free Cloudflare Worker that makes large media (mp4/webm/…) served over Range
requests actually cache on Free/Pro/Business plans, cutting origin egress dramatically.
In production at kinobd.net this reclaimed ~19% of a zone's total traffic (≈240 GB/day, ~33k previously-uncached requests/day) with a single Worker and no origin changes.
Video and audio players fetch files with HTTP Range requests (Range: bytes=0-). Cloudflare
does not cache 206 Partial Content responses on any plan below Enterprise — every range
request is a cache BYPASS that goes straight to your origin. Caching whole files doesn't help
either: a single movie can be many GB, well past Cloudflare's ~512 MB per-object cache limit.
This Worker splits each request into fixed-size, boundary-aligned 4 MB chunks, stores every
chunk in the edge cache as its own cacheable 200 object (…?__c=<n>), and reassembles a
correct 206 for the client. The player is none the wiser — it asks for a byte range and gets
exactly that range.
Two viewers of the same file never request identical byte ranges, but aligned chunks always coincide — which is the only way a shared cache actually accumulates.
It is fail-open: any error, timeout, or unexpected origin response falls through to a plain passthrough. Delivering the media always wins; the Worker can never become a point of failure.
npm i -g wrangler # or: npx wrangler
git clone https://github.com/KinoBD/cloudflare-range-cache
cd cloudflare-range-cache
# edit wrangler.toml → set your route (the media hostname/path you want cached)
wrangler deployPoint a route at the media path you serve (e.g. cdn.example.com/media/*). That's it — no origin
changes. You can confirm it's active from the response header X-Chunk-Cache: worker and rising
cf-cache-status: HIT on the internal chunk requests.
- Request has a
Range? If not, passthrough. - Compute the aligned chunk(s) that cover the requested bytes.
- For each chunk: serve from
caches.default; on a miss, fetch that exact aligned range from origin, repackage the206as a cacheable200(X-Full-Length,X-Src-Type), store it. - Stream the requested slice of each chunk back to the client as a single correct
206— headers first, body as chunks arrive, so playback starts immediately.
Edit the constants at the top of src/worker.js:
| Constant | Default | Meaning |
|---|---|---|
CHUNK |
4 * 1024 * 1024 |
Chunk size. Smaller = more subrequests; larger = worse cross-viewer reuse. |
MAX_CHUNKS |
64 (256 MB) |
Guard against absurd ranges; larger ranges are streamed, so memory is constant. |
TTL |
604800 (7 days) |
Edge cache lifetime. Media segments are immutable. |
- Origin must support
Range(respond206withContent-Range). If it doesn't, the Worker passes through. - Suffix ranges (
bytes=-500) are passed through (rare in practice). - Content type is taken from the origin response, so mixed content (e.g.
.vttalongside mp4) under the same route works.
Built and battle-tested by kinobd.net, an online cinema aggregator, to serve large video over Cloudflare at scale without Enterprise pricing. Open-sourced because the technique is broadly useful and there was no clean, self-contained implementation.