Service Workers + Offline Strategy: Cache First, Network First, Update Lifecycle
A service worker runs separately from the page and can intercept requests, populate caches, serve fallback responses, and control how the app behaves when the network is unavailable or slow.
The most common mistake is treating service workers as “cache everything and go offline.” That approach often creates stale UI, broken deploys, or users stuck on incompatible versions. Strong candidates explain both the upside and the operational risks.
A strong answer usually separates three layers:
- app shell: static UI and assets that can often be cached aggressively
- dynamic data: responses whose freshness depends on product semantics
- update flow: how new service worker code, new assets, and old tabs interact during deployment
Quick Navigation: Service Worker Mental Model • Lifecycle: register, install, activate, fetch • Cache Storage vs HTTP Cache • Core Cache Strategies • Offline UX Is a Product Decision • Offline Fallbacks and App Shell Thinking • Update Lifecycle and Stale Worker Pitfalls • Precache vs Runtime Caching
Quick Decision Guide
Senior-Level Decision Guide:
- Use cache-first for versioned static assets like JS, CSS, fonts, and logos. - Use network-first for critical data where freshness matters more than speed. - Use stale-while-revalidate when immediate response matters and slight staleness is acceptable. - Treat update lifecycle as a first-class design concern: stale workers and stale app shells cause real production bugs. - Separate offline shell from network-dependent data. - Remember that service workers are a programmable request layer, not a reason to ignore HTTP caching semantics.
Interview framing: Service workers are a programmable network layer for resilience and caching, not just a PWA checkbox.
Service Worker Mental Model
A service worker is not part of the page's normal JavaScript runtime.
It runs in its own worker context and can listen for lifecycle and network-related events.
High-level architecture
Page
|
| register()
v
Service Worker
|
| intercept fetch
+--> Cache Storage
|
+--> NetworkKey properties
Practical mental model
Think of the service worker as a programmable proxy sitting between the page and the network.
Lifecycle: register, install, activate, fetch
A service worker usually goes through these major phases:
1) Register
The page registers a service worker script.
2) Install
The browser installs the new worker. This is often where apps pre-cache shell assets.
3) Waiting
If an older worker is still controlling open pages, the new worker may wait rather than taking over immediately.
4) Activate
The new worker becomes active. This is typically where old caches are cleaned up.
5) Fetch
The active worker can intercept matching requests and decide whether to serve cache, network, fallback, or a combination.
Why lifecycle matters
The lifecycle is not just API trivia. It determines:
Important lifecycle nuance
By default, a newly installed service worker does not immediately take over already-open pages. That is why skipWaiting() and clients.claim() are common interview talking points.
Cache Storage vs HTTP Cache
A common confusion is treating service worker cache and browser HTTP cache as the same thing.
They are related, but different.
HTTP cache
Cache-ControlCache Storage API
Mental model
Request
|
Service Worker logic
|
+--> Cache Storage API
|
+--> fetch()
|
+--> browser HTTP cache may still apply
+--> networkInterview framing
A strong answer makes clear that service workers add a programmable caching layer, but HTTP caching semantics still matter.
Core Cache Strategies
Cache First
Return cached response if available; otherwise fetch from network and store it.
Best for: hashed static assets, fonts, icons, logos, stable shell files.
Risk: stale resources if URLs are not versioned properly.
Network First
Try network first; fall back to cache if network fails or times out.
Best for: dynamic data like feed content, dashboards, or inventory-like data.
Risk: poor-network latency unless you define good fallbacks.
Stale While Revalidate
Return cached response immediately, then refresh in background.
Best for: content where perceived speed matters and small staleness is acceptable.
Risk: users may briefly see stale content.
Cache Only / Network Only
Usually niche and used when behavior needs to be very explicit.
Strategy mental model
Cache First:
cache -> network fallback
Network First:
network -> cache fallback
Stale While Revalidate:
cache immediately + refresh in backgroundOffline UX Is a Product Decision
Good offline design is not just technical caching. It requires product decisions about what remains usable without network.
Examples:
A strong architecture usually separates:
Interview framing
Offline-first does not mean every feature must work fully offline. It means the experience degrades intentionally instead of failing chaotically.
Offline Fallbacks and App Shell Thinking
A common pattern is to pre-cache a minimal app shell and optionally an offline fallback page.
Example idea
/offline.htmlWhy this helps
When navigation fails because the network is unavailable, the app can still return something meaningful instead of a browser error page.
Navigation fallback flow
User navigates
|
Service worker tries network/cache strategy
|
|-- success -> normal response
|
|-- failure -> offline fallback pageSenior insight
An offline fallback is not just a technical trick. It is part of UX design and should clearly communicate what still works and what does not.
Update Lifecycle and Stale Worker Pitfalls
The hardest production issue is often not fetch strategy, but update handling.
Common failures:
Why this happens
A new service worker may install, but the old one may still control open tabs until activation conditions are met.
Common tools
activateskipWaiting()clients.claim()Trade-off
Immediate takeover can reduce stale-version problems, but forced activation may also surprise users if the page state and cached assets are mid-session.
Precache vs Runtime Caching
A strong system design answer distinguishes between assets you know ahead of time and resources discovered during usage.
Precache
Assets are added intentionally during install.
Good for:
Runtime caching
Requests are cached as users actually encounter them.
Good for:
Why this matters
Pre-caching too much increases install size and update pain.
Runtime caching gives flexibility, but can be less predictable if not designed carefully.
Common Pitfalls
1) Caching HTML too aggressively
This can trap users on an old app shell after deploy.
2) Caching API data without freshness policy
Users may see stale prices, stale dashboards, or misleading account state.
3) Forgetting cache cleanup
Old caches accumulate and waste storage or serve outdated resources.
4) Mixed-version deploy bugs
Old HTML + new JS or old worker + new assets can create hard-to-debug production failures.
5) Using one strategy for everything
Different resources need different strategies.
6) Ignoring service worker scope and control timing
A page may not be controlled immediately after registration, which confuses many developers.
Workbox and Practical Abstractions
In real projects, many teams use Workbox rather than hand-writing every route and strategy.
Why:
Interview framing
You should understand the underlying concepts even if a library like Workbox handles the implementation details.
Interview Scenarios
Scenario 1: News or content app
Strong answer:
Scenario 2: Admin dashboard
Strong answer:
Scenario 3: E-commerce PWA
Strong answer:
Scenario 4: Users stuck on an old version after deploy
Likely causes:
Scenario 5: “Should we make the whole app offline-first?”
Strong answer: