When a Progressive Web App Is the Right Call
A progressive web app is a website that uses a service worker, a web app manifest and HTTPS to behave like an installed application. It can cache its own code and data, launch from the home screen in a standalone window, and receive push notifications. It is still a website, which means it is indexable, linkable and updatable without an app store review.
PWAs fit best when reach matters more than deep device access. Field-service tools used on shared Android tablets, B2B ordering portals, content and commerce sites with heavy mobile traffic, and internal apps that need to run on whatever hardware staff already own are all strong candidates. If your roadmap depends on Bluetooth peripherals on iPhone, background location, HealthKit or rich widgets, native or cross-platform mobile development is usually the better fit.
| Factor | Progressive web app | Native or cross-platform app |
|---|---|---|
| Distribution | URL, search, QR code; optional store listing via TWA on Google Play | App Store and Google Play review and release cycle |
| Updates | Instant on next load, controlled by service worker | Store review plus user update adoption |
| Offline support | Strong with Cache Storage and IndexedDB | Strong with local databases |
| iOS push notifications | Only for home-screen installs on iOS 16.4+ | Full APNs support |
| Hardware access | Camera, geolocation, some sensors; limited Bluetooth and NFC, especially on iOS | Full platform APIs |
| Discoverability | Indexable by search engines | App store search and ads |
Service Workers and Offline Caching Strategies
The service worker is where a PWA succeeds or fails. It sits between the app and the network, and every fetch decision it makes affects speed, data freshness and storage use. We usually build on Workbox so routing and cache expiration are declarative and testable, then write custom handlers where business rules require them.
Choosing a strategy per resource
- Precache the app shell, fonts and core JavaScript at install time so the first screen renders without the network.
- Stale-while-revalidate for catalog data, avatars and content that can be a few minutes old.
- Network-first with timeout for pricing, inventory and account data, falling back to the last good copy after a short wait.
- Cache-first with expiration for versioned images and static media, with size and age limits to stay under browser storage quotas.
- Network-only for payments, authentication and anything that must never be served from cache.
Offline writes and background sync
Reading cached data is the easy half. For forms, inspections or orders captured offline, we queue mutations in IndexedDB with idempotency keys, then replay them when connectivity returns. Chromium browsers support the Background Sync API; on Safari we replay on the next app open or visibility change. Conflict rules, such as last-write-wins or server-side merge, are agreed with your team before we write the queue.
Safe update flow
A badly handled service worker update can leave users running old code for days. We version caches explicitly, clean up old ones on activate, and show an in-app prompt to reload when a new version is waiting rather than forcing skipWaiting in the middle of a user's task.
Installability, iOS Limits and Web Push
Chromium browsers fire a beforeinstallprompt event that lets you offer installation at the right moment. Safari on iOS does not, so users must use Share and then Add to Home Screen. We design a short, platform-aware install hint for iOS visitors instead of a generic banner that confuses people.
- Web Push on iOS and iPadOS works only after the PWA is added to the home screen, from iOS 16.4 onward.
- Safari can evict script-writable storage for sites that are not used for an extended period, so we treat local data as a cache and keep the server as the source of truth.
- Background execution on iOS is limited; periodic background sync is not available, so time-sensitive work belongs on the server.
- In the EU, Apple's handling of home-screen web apps has changed more than once; we check current behavior before committing to iOS-specific features.
For push, we implement the Push API with VAPID keys, store subscriptions server-side with the user and device context, and send through a queue so a large campaign does not overload your backend. Permission is requested only after a user action that explains the benefit, which keeps opt-in rates healthier and avoids browsers suppressing the prompt.
Our PWA Stack and Performance Budget
Most of our PWAs are built with Next.js or a Vite-based React setup, depending on whether server rendering and SEO are priorities. Server-rendered routes give search engines real HTML; the service worker then handles repeat visits and offline use. We keep JavaScript bundles small with route-level code splitting because a PWA on a mid-range Android phone over 4G is the realistic test device, not a developer laptop.
| Metric | Target (75th percentile, mobile) | What usually moves it |
|---|---|---|
| Largest Contentful Paint | Under 2.5 s | Server rendering, image sizing, precached shell |
| Interaction to Next Paint | Under 200 ms | Less main-thread JavaScript, deferred hydration |
| Cumulative Layout Shift | Under 0.1 | Reserved image and ad space, font loading strategy |
If you also want a Google Play presence, we can wrap the PWA as a Trusted Web Activity with Digital Asset Links. That keeps one codebase while letting Android users find you in the store.
Security and Quality Assurance
Service workers are powerful, so their scope and caching rules get the same review as backend code. We never cache authenticated API responses in shared caches, we clear user-specific caches and IndexedDB on logout, and we set a strict Content Security Policy. Tokens live in HttpOnly cookies where the architecture allows it, not in localStorage.
- Automated Lighthouse and Web Vitals checks in CI with failing thresholds.
- Playwright tests that simulate offline mode, flaky networks and service worker upgrades.
- Manual testing on real iPhones and Android devices across Safari, Chrome and Samsung Internet.
- Storage quota and eviction testing for apps that hold large offline datasets.
Timeline and Cost Factors
A focused PWA with an app shell, a handful of offline-capable screens and push notifications often lands in the $40k–$100k range over 8–14 weeks. Complex offline sync, large data sets on device, or heavy integrations push budgets into the mid-complexity range. These are typical market estimates and vary with scope; our app development cost guide breaks down the drivers in more detail.
- How much of the app must work offline, and whether offline writes need conflict handling.
- Number of user roles and screens.
- Existing APIs versus new backend work.
- SEO requirements, which favor server rendering.
- Whether you also want a Play Store listing through a Trusted Web Activity.
We usually start with a short discovery sprint that maps routes to caching strategies and confirms which device features you truly need. You can see how that sprint fits into the rest of delivery in our step-by-step project process, and we share the resulting route map with you before any build work is priced.
Why Teams Choose Us for PWA Work
We will tell you early if a PWA is the wrong tool. Plenty of teams come to us asking for a PWA when their roadmap actually needs native Bluetooth or background location, and the cheapest project is the one you do not have to rebuild a year later.
When a PWA does fit, you get engineers who treat the service worker as production infrastructure, document every caching decision, and hand over a codebase your own team can extend. If you need a broader browser-based product, our web application development team works from the same stack.