SwoffSwoff

Caching Strategies

6 strategies, patterns, reactive, timeout, cache eviction.

Swoff provides 6 caching strategies that run in the Service Worker. Every fetch event is intercepted, matched against your configured patterns, and handled by the appropriate strategy — no manual route registration needed.

This guide is purely conceptual. You don't need to import any swoff API for caching strategies to work. Everything here is configured in swoff.config.json. Strategies activate automatically once the Service Worker is registered via initServiceWorker(). No code changes required — works the same in React, PHP/Laravel, HTMX, or vanilla HTML.

For the internal mechanics of strategy resolution, serveFromCache, the fallback chain, the reactive entry lifecycle, and navigation mode rules, see the Caching System architecture.

Preconditions

Status

Already on by default. After swoff init, the generated SW applies these default patterns:

PatternStrategyBehavior
/api/*network-firstTry network, fall back to cache
/static/*cache-firstServe from cache on hit, fetch from network on miss

The 6 strategies

{
  "features": {
    "serviceWorker": {
      "strategy": {
        "default": "cache-first",
        "patterns": {
          "/api/*": "network-first",
          "/static/*": "cache-first"
        },
        "timeout": 10,
        "reactive": {
          "defaults": {
            "staleTime": 0,
            "refetchInterval": 0,
            "refetchOnReconnect": false,
            "refetchOnFocus": false
          }
        }
      }
    }
  }
}
StrategyHow it decidesBest for
cache-firstCache hit → serve from cache. Cache miss → fetch and cache. No background refresh.Static assets (JS, CSS, images)
network-firstFetch from network first. Network fails or times out → serve from cache. Cache miss → fallback.API responses that need freshness
stale-while-revalidateCache hit (fresh or stale) → serve from cache + always trigger background refresh. Cache miss → fetch normally.Content that can serve slightly stale data
cache-onlyCache hit → serve from cache. Never fetches from network. Cache miss → fallback.Immutable assets, precached content
network-onlyBypasses SW entirely (early return). Browser handles the request directly. Never cached.Non-cacheable requests, analytics beacons
reactiveCache hit + fresh (within staleTime) → serve. Cache hit + stale → serve + background refresh. Cache miss → fetch and cache. Refreshes only when past staleTime.Dashboard data, polling, focus/refetch patterns

Pattern matching

URL patterns use glob syntax:

PatternMatches
/api/*/api/notes, /api/users (single segment)
/api/**/api/notes/123, /api/users/456/posts (any depth)
/static/*.js/static/app.js, /static/vendor.js
!/api/auth/**Negation — excludes auth routes

Patterns can be a strategy name string or an object with per-route overrides:

{
  "patterns": {
    "/api/notes": {
      "strategy": "reactive",
      "staleTime": 30,
      "refetchInterval": 60,
      "refetchOnFocus": true
    },
    "/api/search/*": {
      "strategy": "network-first",
      "timeout": 5
    }
  }
}

Request-level overrides

Any HTTP client (native fetch, Axios, HTMX, PHP, curl) can override strategy behavior at call time by sending these headers:

X-SW-Strategy: stale-while-revalidate
X-SW-Stale-Time: 30
X-SW-Refetch-Interval: 60
// Browser — native fetch
fetch("/api/notes", {
  headers: { "X-SW-Strategy": "reactive" },
});

// HTMX — via hx-headers
<button hx-get="/api/notes" hx-headers='{"X-SW-Strategy": "network-first"}'>
  Load Notes
</button>;

Available headers: X-SW-Strategy, X-SW-Stale-Time, X-SW-Refetch-Interval, X-SW-Refetch-On-Focus, X-SW-Refetch-On-Reconnect. The refetch* and staleTime options only apply to the reactive strategy — other strategies ignore them.

These headers are consumed by the SW fetch handler and automatically stripped before the request is forwarded to the network. No external server ever sees X-SW-* headers — safe to use with any third-party or cross-origin API.

Config

{
  "features": {
    "serviceWorker": {
      "strategy": {
        "default": "cache-first",
        "timeout": 10,
        "maxRuntimeCacheAge": 2592000,
        "normalizeKey": false,
        "ignoreQueryParams": [],
        "patterns": {},
        "reactive": {
          "defaults": {
            "staleTime": 0,
            "refetchInterval": 0,
            "refetchOnReconnect": false,
            "refetchOnFocus": false
          }
        }
      }
    }
  }
}
  • strategy.default — fallback strategy when no pattern matches or header override is present. One of: "cache-first", "network-first", "stale-while-revalidate", "cache-only", "network-only", "reactive".
  • strategy.timeout — fetch timeout in seconds applied to all SW-initiated network requests. Default: 10. If the fetch doesn't respond within this time, the strategy falls back (e.g., network-first returns cached content).
  • strategy.maxRuntimeCacheAge — maximum age in seconds for runtime-cached entries. Default: 2592000 (30 days). Older entries are pruned during SW activation.
  • strategy.normalizeKey — sort query parameters alphabetically before hashing the cache key. Default: false.
  • strategy.ignoreQueryParams — array of query parameter names to strip from the cache key (e.g. ["_rsc"] for Next.js RSC payloads).
  • strategy.patterns — URL glob pattern → strategy config or strategy name. When the value is an object (per-route override):
    • strategy — the strategy to apply
    • timeout — per-route fetch timeout override (inherits strategy.timeout)
    • staleTime — seconds before a cached response is considered stale (reactive only). 0 means every request after the first triggers a background refresh.
    • refetchInterval — poll interval in seconds (reactive only)
    • refetchOnFocus — refetch when tab regains focus (reactive only)
    • refetchOnReconnect — refetch when network returns (reactive only)
  • strategy.reactive.staleTime — default: 0.
  • strategy.reactive.refetchInterval — default: 0 (no polling).
  • strategy.reactive.refetchOnReconnect — default: false.
  • strategy.reactive.refetchOnFocus — default: false.
  • Caching System architecture — strategy resolution flow, reactive entry lifecycle, navigation serveFromCache and fallback chain, HTML cache isolation
  • Library Comparison — Swoff vs Workbox / Serwist / vite-plugin-pwa / next-pwa

On this page