Cache API Responses in a Service Worker
Apply a stale-while-revalidate strategy in a service worker so repeat visits render instantly and refresh in the background.
Task
Implement stale-while-revalidate caching for API GET requests in a service worker.
When to use this
Repeat visits re-request the same data, making the app feel slow even though the data rarely changes.
Prerequisites
- A service worker registered
- A cache API available
- API GET endpoints
Steps
1. Serve cached responses and refresh in the background.
self.addEventListener('fetch', (event) => {
const { request } = event;
if (request.method !== 'GET') return;
event.respondWith((async () => {
const cache = await caches.open('api-v1');
const cached = await cache.match(request);
const fetched = fetch(request).then((res) => { cache.put(request, res.clone()); return res; });
return cached || fetched;
})());
});Expected output: Repeat requests return the cached response while a fresh one is fetched for next time.
2. Verify cached responses are served and updated.
curl -s http://localhost:4321/api/data | head -c 40
# reload and confirm the response is refreshed from the networkExpected output: The cache is populated on first load and updated in the background on later loads.
Troubleshooting
Problem
Stale data shown too long
Solution
Version the cache name and expire entries; avoid caching authenticated mutations.
Problem
Cache breaks auth
Solution
Do not cache requests carrying credentials unless explicitly scoped.
Limitations
- Stale-while-revalidate shows stale data briefly.
- Cache storage is limited and evictable.
- Requires careful versioning.
What this recipe does
Implement stale-while-revalidate caching for API GET requests in a service worker.
Repeat visits re-request the same data, making the app feel slow even though the data rarely changes.
Prerequisites
- A service worker registered
- A cache API available
- API GET endpoints
Procedure
- Serve cached responses and refresh in the background.
self.addEventListener('fetch', (event) => {
const { request } = event;
if (request.method !== 'GET') return;
event.respondWith((async () => {
const cache = await caches.open('api-v1');
const cached = await cache.match(request);
const fetched = fetch(request).then((res) => { cache.put(request, res.clone()); return res; });
return cached || fetched;
})());
});
Expected result: Repeat requests return the cached response while a fresh one is fetched for next time.
- Verify cached responses are served and updated.
curl -s http://localhost:4321/api/data | head -c 40
# reload and confirm the response is refreshed from the network
Expected result: The cache is populated on first load and updated in the background on later loads.
How to confirm it worked
Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows repeat visits serve cached responses instantly while the cache refreshes from the network in the background.
Troubleshooting
Stale data shown too long — Version the cache name and expire entries; avoid caching authenticated mutations.
Cache breaks auth — Do not cache requests carrying credentials unless explicitly scoped.
Limitations
- Stale-while-revalidate shows stale data briefly.
- Cache storage is limited and evictable.
- Requires careful versioning.