Introduction
Angular's built-in Service Worker (@angular/service-worker) caches API responses based on the ngsw-config.json configuration. When data groups are misconfigured, dynamic API responses are cached when they should always be fresh:
// Misconfigured: caches POST responses which should never be cached
{
"name": "api-cache",
"urls": ["/api/**"],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100
}
}Users see outdated data, form submissions return cached responses, and the application state becomes inconsistent with the server.
Symptoms
- API responses show outdated data after server changes
- POST/PUT responses are cached when they should be fresh
- Different users see each other's data (cache collision)
- Data updates on the server but the app shows old values
- Hard refresh (Ctrl+Shift+R) shows correct data, confirming cache issue
Common Causes
- Data group URL pattern too broad (
/api/**caches all API responses) - Using
performancestrategy (cache-first) for dynamic data - No
timeoutconfigured, so the cache is used even when fresh data is needed - POST/PUT/DELETE responses cached when only GET should be cached
- Cache max age too long for the data's update frequency
Step-by-Step Fix
- 1.Configure data groups with appropriate caching strategy:
- 2.```json
- 3.// ngsw-config.json
- 4.{
- 5."index": "/index.html",
- 6."dataGroups": [
- 7.{
- 8."name": "api-fresh",
- 9."urls": ["/api/users/", "/api/orders/"],
- 10."cacheConfig": {
- 11."strategy": "freshness",
- 12."maxSize": 50,
- 13."maxAge": "1m",
- 14."timeout": "5s"
- 15.}
- 16.},
- 17.{
- 18."name": "api-static",
- 19."urls": ["/api/config", "/api/categories"],
- 20."cacheConfig": {
- 21."strategy": "performance",
- 22."maxSize": 10,
- 23."maxAge": "24h"
- 24.}
- 25.}
- 26.]
- 27.}
- 28.
` - 29.-
freshness: Network-first, falls back to cache when offline - 30.-
performance: Cache-first, falls back to network when cache misses - 31.Exclude mutation endpoints from caching:
- 32.```json
- 33.{
- 34."dataGroups": [
- 35.{
- 36."name": "api-read-only",
- 37."urls": ["/api/products", "/api/products/**"],
- 38."cacheConfig": {
- 39."strategy": "freshness",
- 40."maxSize": 100,
- 41."maxAge": "5m"
- 42.}
- 43.}
- 44.]
- 45.}
- 46.
` - 47.Only GET requests are cached by the Service Worker. POST/PUT/DELETE are never cached.
- 48.Clear the Service Worker cache when needed:
- 49.```typescript
- 50.import { SwUpdate } from '@angular/service-worker';
constructor(private swUpdate: SwUpdate) {}
clearCache() { // Unregister and re-register the Service Worker if (navigator.serviceWorker) { navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { registration.unregister(); }); }); } } ```
- 1.Monitor Service Worker behavior in the browser:
- 2.- Open Chrome DevTools > Application > Service Workers
- 3.- Check the "Cache Storage" section to see cached responses
- 4.- Use the "Update on reload" checkbox during development
- 5.- Verify which requests are served from cache vs network in the Network tab
Prevention
- Use
freshnessstrategy for any data that changes frequently (user data, orders, messages) - Use
performancestrategy only for truly static data (config, categories, translations) - Keep
maxAgeshort for dynamic data (1-5 minutes) and longer for static data (hours) - Set a
timeoutvalue so the Service Worker falls back to network if the cache is stale - Test Service Worker behavior by deploying changes and verifying data freshness
- Add
ngsw-config.jsonto your code review process for every API endpoint addition - Use the
SwUpdateservice to detect and apply Service Worker updates automatically - Monitor cache hit rates in production to identify misconfigured data groups