The Problem
The Angular Service Worker (@angular/service-worker) caches HTTP responses to improve performance. But when configured incorrectly, it serves stale data from the cache instead of fetching fresh responses from the API.
Symptoms
- API data does not update after server changes
- New posts, comments, or settings do not appear
- Refreshing the page shows old data
- Works after clearing browser cache and reloading
- API returns correct data in Network tab but app shows old data
Real Error Scenario
// ngsw-config.json (WRONG: caching everything)
{
"dataGroups": [
{
"name": "api-all",
"urls": ["/api/**"],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
}
]
}This caches ALL API responses for 3 days. Dynamic data like user profiles, messages, and feeds will be stale.
How to Fix It
Fix 1: Use Freshness Strategy for Dynamic Data
{
"dataGroups": [
{
"name": "api-dynamic",
"urls": ["/api/users/**", "/api/posts", "/api/comments/**"],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 50,
"maxAge": "5m",
"timeout": "5s"
}
},
{
"name": "api-static",
"urls": ["/api/config", "/api/categories"],
"cacheConfig": {
"strategy": "performance",
"maxSize": 20,
"maxAge": "1d",
"timeout": "10s"
}
}
]
}freshness: Always tries network first, falls back to cacheperformance: Serves from cache first, updates cache in background
Fix 2: Exclude Write Operations from Caching
{
"dataGroups": [
{
"name": "api-read-only",
"urls": ["/api/products", "/api/categories"],
"cacheConfig": {
"strategy": "performance",
"maxSize": 50,
"maxAge": "1h"
}
}
]
}Only cache GET requests to read-only endpoints. POST, PUT, DELETE should never be cached.
Fix 3: Add Cache-Busting Headers
this.http.get('/api/data', {
headers: { 'Cache-Control': 'no-cache' }
});Fix 4: Programmatically Invalidate Cache
```typescript import { SwUpdate } from '@angular/service-worker';
@Component({...}) export class DataComponent { constructor(private swUpdate: SwUpdate) {}
async refreshData() { if (this.swUpdate.isEnabled) { // Force service worker to check for updates await this.swUpdate.checkForUpdate(); } // Then reload data this.loadData(); } } ```
Fix 5: Disable Service Worker for Specific Requests
this.http.get('/api/realtime-data', {
headers: { 'ngsw-bypass': 'true' }
});The ngsw-bypass header tells the Angular Service Worker to skip this request.