Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cloudflare-range-cache

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.


The problem

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.

The solution

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.

Quick start

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 deploy

Point 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.

How it works

  1. Request has a Range? If not, passthrough.
  2. Compute the aligned chunk(s) that cover the requested bytes.
  3. For each chunk: serve from caches.default; on a miss, fetch that exact aligned range from origin, repackage the 206 as a cacheable 200 (X-Full-Length, X-Src-Type), store it.
  4. 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.

Configuration

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.

Limitations

  • Origin must support Range (respond 206 with Content-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. .vtt alongside mp4) under the same route works.

Why this exists

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.

License

MIT © kinobd.net

About

Cache HTTP Range (206 Partial Content) at the Cloudflare edge without Enterprise — a dependency-free Worker that chunk-caches large media. ~19% of zone traffic reclaimed in production at kinobd.net.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages