SwoffSwoff

Library Comparison

Comprehensive comparison with Workbox, Serwist, TanStack Query, and more.

Swoff operates at the browser infrastructure layer — the Service Worker + fetch event — making it work with any backend, frontend, or rendering strategy. See Ecosystem Compatibility.

Libraries Compared

LibraryCategoryApproach
SwoffOffline infra generatorConfig-driven code gen
WorkboxSW toolkitBuild-time + runtime modules
vite-plugin-pwaSW (Vite)Vite plugin wrapping Workbox
SerwistSW (Next.js-first)Build-time + runtime modules
next-pwaSW (Next.js)Workbox wrapper plugin
TanStack QueryServer stateRuntime JS (app-layer)
SWRServer stateRuntime JS (app-layer)
RTK QueryServer stateRuntime JS + Redux
Apollo ClientGraphQL clientRuntime JS (app-layer)
RxDBClient DBRuntime JS
ElectricSQLClient DB (sync engine)Runtime + PGlite WASM
PowerSyncClient DB (sync engine)Runtime + SQLite
TanStack DBClient DB + offline-firstRuntime JS (differential dataflow)

Three tiers of comparison

These tools operate at different layers and solve different problems. Comparisons across tiers are not deficiencies — they reflect different design constraints.

Tier 1 — SW toolkits (same layer): Workbox, Serwist, vite-plugin-pwa, next-pwa. These intercept fetch at the Service Worker, cache HTTP responses, and serve offline fallbacks. Same layer as Swoff — apples-to-apples comparison. Each row represents a genuine feature gap or design tradeoff.

Tier 2 — Server-state libraries (app layer in-memory): TanStack Query, SWR, Apollo Client. These manage query state in memory with stale-while-revalidate patterns. They do not intercept HTTP, cache responses, or provide offline navigation. Swoff operates below them at the HTTP cache layer — their caching concern is already absorbed by Swoff. They become optional reactivity layers on top of Swoff-cached data. Prefer your library's data freshness? Configure its routes as "network-only" in strategy.patterns to opt them out of SW caching — Swoff still handles offline navigation and static assets. Features marked "—" are out of scope for their paradigm, not gaps.

Tier 3 — Client databases (local DB + sync): RxDB, ElectricSQL, PowerSync, TanStack DB. These embed a local database engine and synchronize with the server. They solve local data queries and conflict resolution at the cost of schema management, WASM bundle size, and no offline app skeleton. A different paradigm, not a direct alternative. Configure their sync endpoints as "network-only" in strategy.patterns — Swoff handles offline navigation while the local DB manages its own sync protocol.

Feature Matrix

Tier 1: SW Toolkits

FeatureSwoffWorkboxSerwistnext-pwavite-plugin-pwa
SW code generation✅ Full source🟡 Partial runtime🟡 Partial runtime🟡 Partial runtime🟡 Partial runtime
Disk-backed cache storage✅ Cache API✅ Cache API✅ Cache API✅ Cache API✅ Cache API
Survives hard navigation
Caching strategies✅ 6✅ 5✅ 5✅ 5✅ 5
Navigation modes✅ 3 (spa, default, ssr)
HTML cache isolation✅ Content-Type routing
Auto-prefetch on client nav✅ pushState interceptor
Request batching (coalescing)✅ 50 ms window
Real-time data & push invalidation✅ Built-in SSE/WS
Precaching: non-blocking✅ After activate (background)🟡 During install (blocks activation)🟡 During install (blocks activation)🟡 During install (blocks activation)🟡 During install (blocks activation)
Precaching: checkpoint resume✅ IndexedDB per-batch❌ Full re-download❌ Full re-download❌ Full re-download❌ Full re-download
Precaching: progress events✅ Built-in sw-progress DOM event🟡 Plugin required🟡 Limited🟡 Limited🟡 Plugin required
Precaching: client resume✅ Visibility + online → RESUME_PRECACHE
Precaching: version reset✅ Content hash of asset list🟡 Revision manifest🟡 Revision manifest🟡 Revision manifest🟡 Revision manifest
Tag-based invalidation✅ URL/op-name auto-tags
Cascading tag dependencies✅ Client-expanded
Tag introspection✅ URLs ↔ tags
Cross-tab invalidation sync✅ SW broadcast
Offline write queue✅ IndexedDB🟡 Basic🟡 Basic🟡 Basic🟡 Basic
Queue: background sync✅ SW via sync API✅ Plugin✅ Plugin✅ Plugin✅ Plugin
Queue: per-mutation online check✅ Before each
Queue: progress tracking✅ Per-item + batch
Config-driven setup✅ Single file✅ workbox-config🟡 Config + code🟡 Config + setup🟡 Config + plugin
Build-tool agnostic✅ Any✅ Any🟡 Vite, Next.js, SvelteKit, etc.❌ Next.js only🟡 Vite ecosystem
Framework adapters✅ 14🟡 Minimal🟡 Limited🟡 Next.js only🟡 Vite plugins
Auditable generated code✅ Every file🟡 Only SW🟡 Only SW🟡 Only SW🟡 Only SW
Auth module✅ Bearer/cookie/custom, 401 recovery, eviction
PWA: manifest generation✅ From config✅ From config🟡 Via plugin✅ From config✅ From config
PWA: icon generationnpx @swoff/assets🟡 Via plugin
PWA: push notifications✅ Built-in SW handler🟡 Manual🟡 Manual🟡 Manual🟡 Manual
PWA: install prompt managementisInstallable/promptInstall🟡 registerSW🟡 registerSW
Resource monitoring✅ Global timeout, storage quota, notifications🟡 Per-strategy timeout only🟡 Per-strategy timeout only🟡 Per-strategy timeout only🟡 Per-strategy timeout only
Runtime deps0 kB (generated code)~30 kB SW runtime~35 kB SW runtime~30 kB SW runtime~30 kB SW runtime
Setup cost1 config fileConfig + importsConfig + codeConfig + setupConfig + plugin

Tier 2: Server-State Libraries (App-Layer In-Memory)

Swoff works below these libraries at the HTTP cache layer. Features marked "—" are out of scope for the app-layer paradigm, not gaps in the library.

FeatureSwoff (SW HTTP cache)TanStack Query / SWR / RTK QueryApollo Client
Cache storageCache API (disk, survives nav)In-memory (lost on nav)In-memory normalized
Caching strategies6 (cache-first, network-first, etc.)1 (stale-while-revalidate)fetchPolicy-based
Offline app skeleton✅ Built-in (HTML/CSS/JS cached)❌ Not provided❌ Not provided
Native fetch interception✅ Every fetch()❌ Only through queryFn❌ Only through client
Third-party API caching✅ Yes❌ No❌ No
Precaching✅ Background, checkpoint resume❌ N/A❌ N/A
Offline navigation✅ 3 modes, fallback chain❌ N/A❌ N/A
Real-time data✅ Built-in SSE/WS🟡 Polling on refetchInterval🟡 Subscriptions
Tag-based invalidation✅ URL/op-name, glob, cascading✅ Query-key based🟡 Custom
Body-hash GQL caching✅ SHA-256❌ N/A🟡 In-memory only
Offline write queue✅ IndexedDB + Background Sync❌ In-memory (lost on close)
Auth module✅ Full (eviction, 401, headers)❌ Developer handles❌ Developer handles
Runtime deps0 kB (generated code)~3.8 kB gzip~15 kB gzip

Tier 3: Client Databases (Local DB + Sync Engine)

Client databases solve local data queries and conflict resolution — a fundamentally different problem from HTTP caching. Features marked "—" are design tradeoffs, not gaps.

FeatureSwoff (SW HTTP cache)RxDBElectricSQL / PowerSyncTanStack DB
ParadigmHTTP cache layerLocal DB + sync engineLocal DB + sync engineDifferential dataflow
Offline app skeleton✅ Built-in❌ Requires separate SW❌ Requires separate SW❌ Requires separate SW
Local SQL queries❌ Server-shaped only✅ MongoDB-like queries✅ SQL✅ Query API
Conflict resolution❌ Last-write-wins✅ CRDTs✅ Custom merge✅ CRDTs
Schema required✅ No❌ Yes❌ Yes❌ Yes
WASM download✅ None✅ None❌ 2–3 MB SQLite WASM✅ None
Server as source of truth✅ Yes❌ Diverges during sync❌ Diverges during sync❌ Diverges during sync
Auto-clear on logoutclearAuth()❌ Data persists❌ Data persists❌ Data persists
Setup cost1 config fileSchema + DB + syncSchema + DB + sync + server adapterSchema + DB + sync + server adapter
Runtime deps0 kB (generated code)~40 kB gzip~40 kB gzip + WASM~6 kB + SQLite WASM

Where to find design-level rationale

Architecture docs explain how Swoff works internally — if you want to understand the design decisions behind a feature, start there:

On this page