Switch your phone to airplane mode and reload the web app your field staff use. If you get the browser's offline page, that is what a delivery agent sees every time the signal drops between two villages. A logistics firm in Pune with riders across Maharashtra pin codes hits this daily, and the usual answer is an Android app, an iOS app and two release processes. A Progressive Web App tries to cover both with one web codebase that installs and keeps working offline, and it does that well right up until you hit a platform limit.
Three pieces make a web app a PWA
A PWA is an ordinary web app built with HTML, CSS and JavaScript, plus three additions.
A web app manifest tells the browser the app's name, icon and display mode, so it can be installed to the home screen and open without the address bar. A service worker is a script that sits between the page and the network and decides what to answer from a local cache. HTTPS is required, because a script with that much control over requests cannot be allowed to arrive over a connection someone could tamper with.
Push notifications and background sync build on the service worker, where the browser and operating system allow them.
- 01Page requestsa file or data
- 02Service workerchecks its rules
- 03Cachehit: answer locally
- 04Networkmiss: fetch and store
Each type of resource gets its own rule for cache or network.
What a rider in the field actually gets
The day's route list loads once at the depot on Wi-Fi. Through the afternoon, each delivery marked done is queued on the phone. When the phone finds a tower again, the queue syncs. The rider does not have to think about any of it, which is the point.
Repeat visits are quick because the app shell, the HTML, CSS and JavaScript for the interface, comes from the cache instead of the network. One codebase runs on the rider's phone, the supervisor's tablet and the dispatcher's desktop. Installation happens from the browser with no store review. And an update reaches everyone on the next load, which is a relief for anyone who has had field staff on four different versions of an APK.
Pick a caching rule for each resource
Offline does not happen by itself. The service worker does exactly what you tell it, so every type of resource needs a written rule.
Static assets, such as the app shell, icons and fonts, can be served cache-first and replaced on the next release. Data that changes, such as delivery status, prices or stock, should usually go network-first with the cached copy as a fallback. With Workbox, a widely used service worker library from the Chrome team, that looks like this:
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';
registerRoute(({ request }) => ['style', 'script', 'font'].includes(request.destination),
new CacheFirst({ cacheName: 'shell' }));
registerRoute(({ url }) => url.pathname.startsWith('/api/deliveries'),
new NetworkFirst({ cacheName: 'deliveries', networkTimeoutSeconds: 4 }));
When the app falls back to cached data, the screen has to say so. A rate card shown from yesterday's cache with no label is how a sales rep quotes the wrong price to a dealer.
Where PWA projects go wrong
The first mistake is shipping a service worker with no caching plan and calling it offline support. In the field that gives a blank screen, which is worse than the website you had before.
The second is the reverse. Cache too aggressively and users keep seeing last week's data after a release, and the support WhatsApp group fills with screenshots.
The third is updates. A new service worker waits until every tab running the old one is closed before it takes over. A rider who never closes the app can run an old version for days. Detect the waiting worker, show a small "new version ready" bar and reload when they tap it.
Then there are offline writes. When a rider edits a record offline and the dispatcher edits the same record in the office, something has to decide which version wins. That rule belongs to the business, and no framework will pick it for you.
Last, platform support is uneven. Installation prompts, push notifications and device features like Bluetooth differ across browsers and operating systems, and iOS has historically supported less than Android. A PWA also does not appear in an app store unless you wrap it, which brings back store review and its costs.
PWA or native
| PWA | Native app | |
|---|---|---|
| Codebase | One web codebase | One per platform, or a cross-platform toolkit |
| Distribution | Link and browser install | App stores |
| Device features | What browsers expose | Full access |
| Updates | On next load | Store release, then user update |
| Offline | Designed per feature | Designed per feature |
Note the last row. Native apps do not get offline behaviour for free either. If you are weighing toolkits on the native side, our post on native versus cross-platform apps goes through that decision.
When a PWA is the right call
A PWA is a sound choice when your users are on weak or expensive connections, when separate iOS and Android apps are hard to justify, or when people reach you through links, search and WhatsApp forwards rather than a store. A supply app for kirana shopkeepers who get a link from the distributor's sales rep fits that well.
It is a weaker choice when the product depends on deep hardware access, heavy background work or being found in app stores. For those, our mobile app development team usually recommends a native or cross-platform build instead.
Browsers keep adding device capabilities, but support varies. Check each feature you plan to rely on against the browsers your users actually carry. For field staff in India that usually means Chrome on a mid-range Android phone, plus a few iPhones among the managers, and both belong in the test plan.
Build one offline task first
You can add PWA features to an existing site in stages: HTTPS and a manifest, then a service worker for static files, then offline behaviour for one feature. Each stage leaves you with something that works, so you can stop at any of them. The same staged approach runs through our web development projects.
Pick the one task your users most need on a bad connection, such as viewing a booking or marking a delivery done. Build only that, with a written caching rule for every request it makes. Then open Chrome DevTools, go to the Application panel, tick Offline and run the task end to end. Repeat it on the cheapest phone your staff use and on the oldest iOS version you support, before anyone demos it to management.

