Skip to main content
Blaze ships two performance-focused middleware modules: cache() integrates with Cloudflare’s Cache API to store and serve responses at the edge, and compress() shrinks response bodies using the Web-standard CompressionStream API. A third module, etag(), complements both by generating cache validators that let browsers skip downloads entirely when content hasn’t changed.

Cache middleware

cache() checks caches.default — the Cloudflare Cache API available in every Worker — before calling downstream handlers. On a cache hit, it returns the stored response immediately. On a miss, it lets the request proceed normally and stores the response in the cache for future requests.
The Cloudflare Cache API is scoped to the datacenter that handles each request. A response cached in Frankfurt is not automatically available in Singapore. For globally consistent caching, combine cache() with a KV-backed strategy or use Cloudflare’s Cache Rules in your dashboard.

CacheOptions reference

Caching GET responses

The middleware respects your existing Cache-Control headers: if your handler already sets Cache-Control, cache() stores the response as-is without overriding it. Only responses with status codes in the 2xx3xx range are stored.

Cache-Control passthrough

ETag middleware

etag() generates a weak ETag for each response body using a fast djb2 hash (no crypto overhead) and handles conditional requests via If-None-Match304 Not Modified. This means repeat visitors skip the download entirely when the content hasn’t changed.

EtagOptions

etag() patches res.json(), res.send(), and res.html() to intercept the response body before it’s sent. If the computed ETag matches the If-None-Match request header, it short-circuits to a 304 Not Modified with no body.

Compress middleware

compress() uses the Web-standard CompressionStream API to pipe response bodies through gzip or deflate compression. It checks the Accept-Encoding request header first, skips already-encoded responses (bodies with a Content-Encoding header), and skips responses below a configurable byte threshold.

CompressOptions

When compression is applied, compress() sets Content-Encoding to the chosen algorithm, removes Content-Length (since the compressed size differs), and appends Accept-Encoding to the Vary header so caches store separate copies for compressed and uncompressed clients.

Combining cache + compress + etag

Layer all three middleware together for maximum performance. Order matters: compress the response first, then generate the ETag from the compressed bytes, then store the compressed + tagged response in the cache.
With this stack, a warm request from a browser with a matching ETag results in:
  1. etag() checks the If-None-Match header against its computed ETag — sends 304 Not Modified immediately if unchanged.
  2. The browser uses its local copy, paying zero bandwidth.
A warm request without a matching ETag (cache already populated) results in:
  1. cache() checks caches.default — cache hit, returns the stored compressed response immediately.
  2. etag() sets the ETag header on the outgoing response.
  3. The browser receives the compressed response and caches the ETag for future requests.
A cold request (cache miss, no prior ETag) results in:
  1. cache() misses — calls next() to run the route handler.
  2. The route handler returns JSON.
  3. compress() streams the body through CompressionStream.
  4. etag() hashes the body, sets the ETag header.
  5. cache() stores the final compressed response in caches.default.
  6. The browser receives the compressed, tagged response.