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

json
// 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

json
{
  "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 cache
  • performance: Serves from cache first, updates cache in background

Fix 2: Exclude Write Operations from Caching

json
{
  "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

typescript
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

typescript
this.http.get('/api/realtime-data', {
  headers: { 'ngsw-bypass': 'true' }
});

The ngsw-bypass header tells the Angular Service Worker to skip this request.