A PWA tier list is only useful if it ranks capabilities by whether they actually work on the devices your users have. This ranking is by cross-browser reality in 2026 — Chromium, Firefox and Safari on both desktop and mobile — not by how exciting the API sounds in a conference talk.
S means it works everywhere including iOS Safari and you can build a product on it. F means it exists in exactly one engine and Apple has publicly declined to implement it. Everything in between is graded on how much fallback code you have to write.
Service Worker + Cache API + Web App Manifest. Universal. Offline shells, precaching and installability work in Chrome, Edge, Firefox and Safari.
Web Push and the Notifications API. Everywhere, with one asterisk: on iOS the user must add the app to the Home Screen first, and permission must be requested from a user gesture.
IndexedDB, Web Share, Media Session, Screen Wake Lock. Broad support, occasional quirks — Safari's storage eviction and Firefox's stricter Share targets mean you still need a fallback path.
Background Sync, Periodic Background Sync, Badging API. Chromium only. Useful, but treat every one of them as an enhancement and keep a foreground retry queue.
File System Access, Web Serial, Web USB. Chromium desktop only, behind permission prompts, and completely absent on iOS. Fine for an internal tool, wrong for a consumer product.
Web Bluetooth and Web NFC. Android Chromium only. Both have been declined on privacy grounds by other vendors, so there is no path to parity. Build a native companion or drop the feature.
Chromium fires beforeinstallprompt so you can defer and show your own button. Safari never fires it — installation is Share, then Add to Home Screen, and you can only detect the result afterwards via display-mode: standalone. Any onboarding flow that assumes a programmatic prompt will silently do nothing for half your users.
Cache Storage and IndexedDB are subject to eviction. Safari aggressively clears script-writable storage for sites the user has not returned to, and every engine will evict under disk pressure. Call navigator.storage.persist(), check navigator.storage.estimate(), and design your app so a cold cache is a slow start rather than a broken screen.
Ship the S and A tiers as your foundation: a service worker with a precached shell, a manifest with proper icons and display: standalone, and push only where it earns its permission prompt. Feature-detect everything from B down with 'BackgroundSync' in window-style checks rather than user-agent sniffing, and keep the non-supporting path as the default code path, not the exception.
Free tools, guides, and resources across the SPUNK13 network.
Visit spunk.bet400+ Free Tools