Documentation Index Fetch the complete documentation index at: https://mintlify.com/cloudflare/workerd/llms.txt
Use this file to discover all available pages before exploring further.
The Cache API provides programmatic control over HTTP caching. You can store responses and retrieve them later, enabling faster subsequent requests and offline functionality.
Overview
Workerd implements a subset of the standard Cache API:
caches.default - Access the default cache
caches.open(name) - Open a named cache
cache.match() - Retrieve cached responses
cache.put() - Store responses
cache.delete() - Remove cached responses
Implementation: src/workerd/api/cache.h and cache.c++
Accessing caches
Default cache
The caches.default cache is always available:
const cache = caches . default ;
Named caches
Open or create a named cache:
const cache = await caches . open ( 'my-cache' );
Storing responses
Use cache.put() to store responses:
export default {
async fetch ( request ) {
const cache = caches . default ;
// Create a response
const response = new Response ( 'Hello World' , {
headers: {
'Content-Type' : 'text/plain' ,
'Cache-Control' : 'public, max-age=3600'
}
});
// Store in cache
await cache . put ( request , response . clone ());
return response ;
}
} ;
Source: src/workerd/api/tests/cache-operations-test.js:52
The Cache-Control header determines caching behavior:
// Cache for 1 hour
const response = new Response ( 'data' , {
headers: {
'Cache-Control' : 'public, max-age=3600'
}
});
await cache . put ( request , response );
// Don't cache
const response = new Response ( 'data' , {
headers: {
'Cache-Control' : 'no-store'
}
});
await cache . put ( request , response ); // Won't be cached
// Server-specific max age
const response = new Response ( 'data' , {
headers: {
'Cache-Control' : 's-maxage=7200, public'
}
});
await cache . put ( request , response );
Source: src/workerd/api/tests/cache-operations-test.js:65
Retrieving responses
Use cache.match() to retrieve cached responses:
export default {
async fetch ( request ) {
const cache = caches . default ;
// Try to get from cache
let response = await cache . match ( request );
if ( response ) {
// Cache hit
return response ;
}
// Cache miss - fetch from origin
response = await fetch ( request );
// Store in cache for next time
await cache . put ( request , response . clone ());
return response ;
}
} ;
Match options
Customize matching behavior:
// Ignore HTTP method (match non-GET requests)
const response = await cache . match ( request , {
ignoreMethod: true
});
Source: src/workerd/api/cache.h:16
Cloudflare’s implementation does not support ignoreSearch or ignoreVary options. Users can remove query parameters before calling put() if needed.
Deleting cached responses
Remove responses from the cache:
const cache = caches . default ;
// Delete a specific response
const deleted = await cache . delete ( request );
if ( deleted ) {
console . log ( 'Cache entry deleted' );
} else {
console . log ( 'Cache entry not found' );
}
Source: src/workerd/api/tests/cache-operations-test.js:97
Delete options
Use the same options as match():
// Delete non-GET requests
const deleted = await cache . delete ( request , {
ignoreMethod: true
});
Cache patterns
Cache-first strategy
Serve from cache, fall back to network:
export default {
async fetch ( request ) {
const cache = caches . default ;
// Try cache first
let response = await cache . match ( request );
if ( ! response ) {
// Fetch from network
response = await fetch ( request );
// Cache the response
await cache . put ( request , response . clone ());
}
return response ;
}
} ;
Network-first strategy
Try network first, fall back to cache:
export default {
async fetch ( request ) {
const cache = caches . default ;
try {
// Try network first
const response = await fetch ( request );
// Update cache
await cache . put ( request , response . clone ());
return response ;
} catch ( error ) {
// Network failed, try cache
const cached = await cache . match ( request );
if ( cached ) {
return cached ;
}
// No cache entry either
return new Response ( 'Offline' , { status: 503 });
}
}
} ;
Stale-while-revalidate
Serve stale content while updating:
export default {
async fetch ( request , env , ctx ) {
const cache = caches . default ;
// Get cached response
const cached = await cache . match ( request );
// Fetch fresh response asynchronously
const fetchPromise = fetch ( request ). then ( response => {
// Update cache in background
ctx . waitUntil (
cache . put ( request , response . clone ())
);
return response ;
});
// Return cached response immediately if available
return cached || fetchPromise ;
}
} ;
Time-based invalidation
Invalidate cache entries after a time period:
export default {
async fetch ( request ) {
const cache = caches . default ;
const response = await cache . match ( request );
if ( response ) {
// Check age
const date = new Date ( response . headers . get ( 'Date' ));
const age = Date . now () - date . getTime ();
// If older than 1 hour, refresh
if ( age > 3600000 ) {
const fresh = await fetch ( request );
await cache . put ( request , fresh . clone ());
return fresh ;
}
return response ;
}
// Not in cache
const fresh = await fetch ( request );
await cache . put ( request , fresh . clone ());
return fresh ;
}
} ;
Cache keys
Cache keys are based on the request URL:
// These are different cache entries
await cache . put (
new Request ( 'https://example.com/api' ),
response1
);
await cache . put (
new Request ( 'https://example.com/api?param=value' ),
response2
);
Custom cache keys
Create custom cache keys by modifying the request:
// Remove query parameters for cache key
function getCacheKey ( request ) {
const url = new URL ( request . url );
url . search = '' ; // Remove query string
return new Request ( url . toString (), request );
}
// Use custom key
const cacheKey = getCacheKey ( request );
let response = await cache . match ( cacheKey );
if ( ! response ) {
response = await fetch ( request );
await cache . put ( cacheKey , response . clone ());
}
Best practices
Response bodies can only be read once. Clone before caching: const response = await fetch ( request );
await cache . put ( request , response . clone ());
return response ;
Set appropriate Cache-Control headers
Handle cache misses gracefully
Always check if match() returns undefined: const cached = await cache . match ( request );
if ( ! cached ) {
// Handle cache miss
}
Use named caches for organization
Separate different types of cached content: const apiCache = await caches . open ( 'api-responses' );
const assetCache = await caches . open ( 'static-assets' );
Implementation notes
The Cache API implementation in workerd:
Only supports GET requests by default
Does not support cache enumeration (keys(), matchAll())
Does not support ignoreSearch or ignoreVary options
Cache keys are based on request URL
Definition: src/workerd/api/cache.h:37
class Cache : public jsg :: Object {
jsg :: Promise < jsg :: Optional < jsg :: Ref < Response >>> match (
jsg :: Lock & js ,
Request :: Info request ,
jsg :: Optional < CacheQueryOptions > options ,
CompatibilityFlags :: Reader flags );
jsg :: Promise < void > put (
jsg :: Lock & js ,
Request :: Info request ,
jsg :: Ref < Response > response ,
CompatibilityFlags :: Reader flags );
jsg :: Promise < bool > delete_ (
jsg :: Lock & js ,
Request :: Info request ,
jsg :: Optional < CacheQueryOptions > options ,
CompatibilityFlags :: Reader flags );
};
Fetch API - Making requests and handling responses
Headers - Managing Cache-Control headers