Custom cache
Control cache programmatically. Use this template to optimize performance and implement custom caching strategies.
// Define configurable cache duration in seconds (default: 30 days)const CACHE_DURATION_SECONDS = 30 * 24 * 60 * 60;
// Define which parts of the request to include in the cache keyconst USE_PATH = true; // Include path in the cache keyconst USE_QUERY_STRING = true; // Include query string in the cache keyconst INCLUDE_HEADERS = ["User-Agent"]; // Headers to include in the cache key
export default {    async fetch(request, env, ctx) {        // Generate a custom cache key based on user preferences        const cacheKey = createCacheKey(request);        console.log(`Retrieving cache for: ${cacheKey.url}.`)
        // Access the default Cache API        const cache = caches.default;
        // Attempt to retrieve the cached response        let response = await cache.match(cacheKey);
        if (!response) {            // Cache miss: Fetch the asset from the origin            console.log(`Cache miss for: ${cacheKey.url}. Fetching from origin...`);            response = await fetch(request);
            // Wrap the origin response for caching            response = new Response(response.body, response);
            // Set Cache-Control headers to define the TTL            response.headers.set("Cache-Control", `s-maxage=${CACHE_DURATION_SECONDS}`);            response.headers.set("x-snippets-cache", "stored");
            // Store the response in the cache            await cache.put(cacheKey, response.clone());        } else {            // Cache hit: Return the cached response            console.log(`Cache hit for: ${cacheKey.url}.`);            response = new Response(response.body, response);            response.headers.set("x-snippets-cache", "hit");
            // Optionally check if the cache should expire based on age            const ageHeader = response.headers.get("Age");            if (ageHeader && parseInt(ageHeader, 10) > CACHE_DURATION_SECONDS) {                console.log(`Cache expired for: ${cacheKey.url}. Deleting cached response...`);                await cache.delete(cacheKey);                response.headers.set("x-snippets-cache", "deleted");            }        }
        // Return the response to the client        return response;    },};
/** * Function to create a custom cache key based on request properties * @param {Request} request - The incoming request object * @returns {Request} - A valid cache key based on the URL */function createCacheKey(request) {    const url = new URL(request.url); // Use the request's base URL    const cacheKey = new URL(url.origin); // Start with the origin (scheme + hostname)
    // Optionally include the path    if (USE_PATH) {        cacheKey.pathname = url.pathname;    }
    // Optionally include the query string    if (USE_QUERY_STRING) {        cacheKey.search = url.search;    }
    // Optionally include specific headers    if (INCLUDE_HEADERS.length > 0) {        const headerParts = INCLUDE_HEADERS.map(header => `${header}=${request.headers.get(header) || ""}`).join("&");        cacheKey.searchParams.append("headers", headerParts);    }
    // Return the constructed URL as the cache key    return new Request(cacheKey.toString(), {        method: "GET"    });}Was this helpful?
- Resources
- API
- New to Cloudflare?
- Products
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark