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:

json
// 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 performance strategy (cache-first) for dynamic data
  • No timeout configured, 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. 1.Configure data groups with appropriate caching strategy:
  2. 2.```json
  3. 3.// ngsw-config.json
  4. 4.{
  5. 5."index": "/index.html",
  6. 6."dataGroups": [
  7. 7.{
  8. 8."name": "api-fresh",
  9. 9."urls": ["/api/users/", "/api/orders/"],
  10. 10."cacheConfig": {
  11. 11."strategy": "freshness",
  12. 12."maxSize": 50,
  13. 13."maxAge": "1m",
  14. 14."timeout": "5s"
  15. 15.}
  16. 16.},
  17. 17.{
  18. 18."name": "api-static",
  19. 19."urls": ["/api/config", "/api/categories"],
  20. 20."cacheConfig": {
  21. 21."strategy": "performance",
  22. 22."maxSize": 10,
  23. 23."maxAge": "24h"
  24. 24.}
  25. 25.}
  26. 26.]
  27. 27.}
  28. 28.`
  29. 29.- freshness: Network-first, falls back to cache when offline
  30. 30.- performance: Cache-first, falls back to network when cache misses
  31. 31.Exclude mutation endpoints from caching:
  32. 32.```json
  33. 33.{
  34. 34."dataGroups": [
  35. 35.{
  36. 36."name": "api-read-only",
  37. 37."urls": ["/api/products", "/api/products/**"],
  38. 38."cacheConfig": {
  39. 39."strategy": "freshness",
  40. 40."maxSize": 100,
  41. 41."maxAge": "5m"
  42. 42.}
  43. 43.}
  44. 44.]
  45. 45.}
  46. 46.`
  47. 47.Only GET requests are cached by the Service Worker. POST/PUT/DELETE are never cached.
  48. 48.Clear the Service Worker cache when needed:
  49. 49.```typescript
  50. 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. 1.Monitor Service Worker behavior in the browser:
  2. 2.- Open Chrome DevTools > Application > Service Workers
  3. 3.- Check the "Cache Storage" section to see cached responses
  4. 4.- Use the "Update on reload" checkbox during development
  5. 5.- Verify which requests are served from cache vs network in the Network tab

Prevention

  • Use freshness strategy for any data that changes frequently (user data, orders, messages)
  • Use performance strategy only for truly static data (config, categories, translations)
  • Keep maxAge short for dynamic data (1-5 minutes) and longer for static data (hours)
  • Set a timeout value 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.json to your code review process for every API endpoint addition
  • Use the SwUpdate service to detect and apply Service Worker updates automatically
  • Monitor cache hit rates in production to identify misconfigured data groups