Implementing Geo-Specific Caching in Cloudflare Workers
Configure Cloudflare Workers to cache responses based on user location, ensuring content is served correctly to users from different countries or regions. This guide covers how to implement caching that distinguishes between users in the US and Canada (region-level caching) and users from other countries (country-level caching).
Problem Overview
By default, Cloudflare may cache content based on the first user’s location, causing users from different regions to see content intended for others. This can be problematic for sites needing geo-specific content delivery.
Solution: Custom Cache Keys and the Vary
Header
To handle geo-specific caching, use a custom cache key and the Vary
header in Cloudflare Workers.
Implementation Steps
-
Create or Edit a Cloudflare Worker:
- Ensure your Worker is set up in the Cloudflare dashboard or deployed via Wrangler.
-
Add the following code:
1addEventListener('fetch', event => { 2 event.respondWith(handleRequest(event.request, event)); 3}); 4 5async function handleRequest(request, event) { 6 let headers = new Headers(request.headers); 7 8 const countryCode = request.cf && request.cf.country ? request.cf.country : 'unknown'; 9 const regionCode = request.cf && request.cf.regionCode ? request.cf.regionCode : ''; 10 11 // Define cache key: region-level for US/CA, country-level for others 12 let cacheKey; 13 if (countryCode === 'US' || countryCode === 'CA') { 14 cacheKey = new Request(`${request.url}?geo=${countryCode}-${regionCode}`, request); 15 } else { 16 cacheKey = new Request(`${request.url}?geo=${countryCode}`, request); 17 } 18 19 const cache = caches.default; 20 let response = await cache.match(cacheKey); 21 22 if (!response) { 23 response = await fetch(request, { headers: headers }); 24 response = new Response(response.body, response); 25 26 response.headers.set('Cache-Control', 'public, max-age=300'); 27 response.headers.set('Vary', 'cf-ipcountry'); 28 if (countryCode === 'US' || countryCode === 'CA') { 29 response.headers.append('Vary', 'cf-regioncode'); 30 } 31 32 event.waitUntil(cache.put(cacheKey, response.clone())); 33 } else { 34 response = new Response(response.body, response); 35 response.headers.set("cf-region", request.cf.region || 'unknown'); 36 response.headers.set("cf-regioncode", regionCode); 37 } 38 39 return response; 40}
Key Points
- Cache Key: Differentiates cached responses based on country for all users and by region for users in the US and Canada.
Vary
Header: Ensures Cloudflare respects caching bycf-ipcountry
and, when applicable,cf-regioncode
.- Cache Behavior:
- First request populates the cache (
MISS
). - Subsequent requests for the same geo-specific content should hit the cache (
HIT
).
- First request populates the cache (
Testing
-
Check Response Headers:
-
Use browser dev tools or
curl
to confirm theCF-Cache-Status
header (HIT
orMISS
). -
Verify the presence of
Vary: cf-ipcountry
andVary: cf-regioncode
(if applicable).Example:
1curl -I https://yourdomain.com/path/to/resource
-
-
Simulate Geo-Access:
- Use a VPN to test access from different locations.
- Ensure content served matches the expected geo-specific version.