A PWA (Progressive Web App) is a web application that can be installed and run like a native app while remaining an ordinary website delivered over HTTPS. Among web applications, the term describes not a framework but a set of browser capabilities: a web app manifest, a service worker and a secure origin, which together enable installation, offline operation and system integration.
The word progressive is essential. A PWA works as a normal web page in any browser and adds capabilities where the browser supports them, so the same codebase serves a basic visitor and an installed user without separate builds or app store distribution.
The building blocks of a PWA
Three technical components define a PWA. Each one has a distinct job, and installability criteria in browsers depend on their presence. The table below summarizes what each component contributes.
| Component | Role | Key details |
|---|---|---|
| HTTPS origin | Secure context for powerful APIs | Required except on localhost |
| Web app manifest | Describes the installed app | JSON with name, icons, start_url, display |
| Service worker | Programmable network proxy | Caching, offline pages, push handling |
| Responsive interface | Fits any screen size | Not a technical gate but expected |
The web app manifest is linked from the HTML head and declares the app name, icons of at least 192 and 512 pixels, a start_url, theme colors and a display mode. Setting display to standalone removes the browser address bar, which makes the installed app look like a native window.
How the service worker enables offline use
A service worker is a JavaScript file that the browser runs on a separate thread, independent of any page. Once registered, it intercepts every network request from pages in its scope through the fetch event and decides whether to answer from the network, from the Cache Storage API or from a combination of both.
The service worker has a strict lifecycle of install, activate and fetch. A new version waits until all tabs using the old version close, unless the code calls skipWaiting. This rule prevents two versions from controlling the same page, but it is also the most common source of confusion when updates seem not to appear.
The choice of caching strategy determines freshness and offline behavior for each kind of resource.
| Strategy | Behavior | Best suited for |
|---|---|---|
| Cache first | Serve cache, fall back to network | Versioned static assets, fonts |
| Network first | Try network, fall back to cache | HTML pages, frequently changing data |
| Stale while revalidate | Serve cache, update in background | Avatars, non-critical API data |
| Network only | Never cache | Payments, analytics beacons |
| Cache only | Never touch network | Precached app shell |
PWA compared with SPA, native and hybrid apps
A PWA is orthogonal to the rendering architecture. An SPA, an MPA or a site built with SSR or SSG can each become a PWA by adding a manifest and a service worker. The useful comparison is therefore with other ways of delivering an app-like experience.
| Model | Distribution | Device access | Update path |
|---|---|---|---|
| PWA | URL, optional store listing | Broad but browser-limited | Instant on next visit |
| Native app | App stores | Full platform APIs | Store review and user update |
| Hybrid app | App stores | Plugins bridge native APIs | Store, sometimes live updates |
| Plain website | URL only | Standard web APIs | Instant |
The main trade-off is reach and update speed against platform depth. A PWA is indexable by search engines and needs no store approval, but it cannot use every hardware feature, and its capabilities differ between browser engines.
Platform support and its limits
Chromium-based browsers on Android and desktop offer the broadest support: an install prompt, push notifications, background sync and file handling. Safari on iOS and iPadOS supports installation through the share menu and, since iOS 16.4, web push for installed apps, but it lacks several background APIs and may evict stored data after periods of inactivity.
Storage quotas are also browser-dependent and not guaranteed. Applications that hold important offline data should request persistent storage with navigator.storage.persist and still design for the possibility that the cache is cleared.
When a PWA is the right choice
The decision depends on audience, connectivity and required device features. The table pairs common situations with a recommended approach.
| Situation | Recommendation | Reason |
|---|---|---|
| Content or commerce site with mobile traffic | PWA | Faster repeat visits, no install friction |
| Field work with unreliable network | PWA with offline data | Service worker and IndexedDB cover gaps |
| Heavy use of Bluetooth, NFC or sensors on iOS | Native app | Browser APIs unavailable there |
| Internal business tool | PWA | One codebase, instant updates |
| Store visibility is critical | PWA packaged for stores or native | Discovery happens in the store |
Common mistakes when building a PWA
- Caching HTML with cache first, which leaves users stuck on an outdated version.
- Forgetting a versioned cache name, so old assets are never cleaned up during activation.
- No offline fallback page, which shows the browser error screen instead of a useful message.
- Treating installation as the goal, while most users never install and still need a fast site.
- Assuming identical behavior on iOS, which leads to broken push or background features.
A practical safeguard is to test the update flow deliberately: deploy a change, verify that the new service worker activates and inform users with a reload prompt when a new version is ready.
A non-technical view
A PWA is a website that can act like an app. You open it in the browser as usual, but you can also add it to your home screen. It then opens in its own window, starts quickly and may even work without an internet connection.
The trick is a small helper program that the website leaves in your browser. It keeps copies of important files so the app can open when the network is slow or missing. Nothing has to be downloaded from an app store, and updates arrive automatically the next time you open it.
A concrete example
A utility company equips its meter inspectors with tablets and a web-based inspection form. Inspectors often work in basements with no mobile signal, and the previous website lost their entries whenever the connection dropped.
The development team turns the existing site into a PWA. A service worker precaches the app shell and forms, inspection records are saved to IndexedDB, and the Background Sync API sends them when the connection returns. The manifest uses standalone display, and inspectors install the app from the browser menu.
Within the first month, lost inspection records fall to zero, and new releases reach every tablet on the next launch without any app store review or manual update.