Safari PWA Limitations on iOS: Why Progressive Web Apps Struggle on Apple Devices
Problem
When I build progressive web apps, Safari on iOS causes major headaches.
I built a PWA with push notifications, background sync, and offline storage. It worked great on Android Chrome. But on iOS Safari, notifications didn’t work. Background sync didn’t exist. Storage got cleared after 7 days.
My PWA was crippled on iOS.
Environment
- iOS Safari 17+
- Testing on iPhone (actual device)
- Service Worker registered
What Happened
I had a standard PWA setup:
// Register service workerif ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js');}
// Subscribe to push notificationsconst subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidKey});On Android Chrome, this worked perfectly. On iOS Safari:
- Push notifications failed
- Background sync was unavailable
- Storage got cleared unexpectedly
The iOS PWA Feature Gap
Here’s what I discovered:
Feature | Chrome | Safari iOS---------------------|--------|------------Push Notifications | ✅ | ⚠️ iOS 16.4+Background Sync | ✅ | ❌Periodic Sync | ✅ | ❌Storage Persistence | ✅ | ⚠️ LimitedFile System Access | ✅ | ❌Web Share API | ✅ | ✅Install Prompt | ✅ Auto| ⚠️ ManualPush Notifications: iOS 16.4+
iOS 16.4 added push notification support for installed PWAs. But:
- Users must install the PWA first
- Notifications only work when PWA is installed
- Older iOS versions don’t support this at all
No Background Sync
Background sync allows offline actions to complete when connectivity returns. iOS Safari doesn’t support this.
// This works in Chrome, not Safariself.registration.sync.register('sync-data');Storage Gets Cleared
iOS Safari may clear website storage after 7 days of no use. This includes:
- IndexedDB
- LocalStorage
- Service Worker cache
For a PWA, this is catastrophic. User data disappears.
Why This Happens
Apple’s Strategic Position
Apple controls both:
- iOS App Store (30% revenue cut)
- iOS Safari (WebKit engine)
PWAs bypass the App Store. There’s a conflict of interest.
PWA success → App Store revenue lossWebKit PWA limitations → Protect App Store revenueiOS Browser Engine Restriction
All iOS browsers must use WebKit. Even Chrome on iOS uses Safari’s rendering engine.
Chrome on iOS = Safari WebKit engineFirefox on iOS = Safari WebKit engineEdge on iOS = Safari WebKit engine
All iOS browsers share Safari's PWA limitationsThis means PWA limitations affect ALL iOS browsers, not just Safari.
How to Work Around It
Solution #1: Feature Detection
Always detect capabilities before using them:
const pwaCapabilities = { serviceWorker: 'serviceWorker' in navigator, pushManager: 'PushManager' in window, backgroundSync: 'SyncManager' in window, persistentStorage: navigator.storage && 'persist' in navigator.storage};
console.log('PWA Capabilities:', pwaCapabilities);This tells me exactly what features I can use.
Solution #2: iOS Push Notification Handling
For push notifications, handle iOS specifically:
async function setupPushNotifications() { if (!('PushManager' in window)) { // iOS doesn't support push // Show in-app notifications instead setupInAppNotifications(); return; }
// Check if we're on a supported iOS version const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
if (isIOS) { // iOS 16.4+ supports push for installed PWAs // Prompt user to install PWA first const isStandalone = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
if (!isStandalone) { showIOSInstallPrompt(); return; } }
// Subscribe to push const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidKey });
return subscription;}Solution #3: Storage Persistence
Request persistent storage to reduce clearing risk:
async function requestPersistentStorage() { if (navigator.storage && navigator.storage.persist) { const isPersisted = await navigator.storage.persist(); console.log(`Storage persisted: ${isPersisted}`); return isPersisted; } return false;}Note: iOS may still clear storage, but this requests protection.
Solution #4: Server-Side Backup
For critical data, sync to server:
async function saveWithBackup(data) { // Try local storage first try { localStorage.setItem('app-data', JSON.stringify(data)); } catch (e) { console.log('Local storage failed'); }
// Always sync to server await fetch('/api/sync', { method: 'POST', body: JSON.stringify(data) });}
async function loadData() { // Try server first const response = await fetch('/api/sync'); if (response.ok) { return response.json(); }
// Fallback to local const local = localStorage.getItem('app-data'); return local ? JSON.parse(local) : null;}Solution #5: iOS Install Detection
iOS doesn’t fire beforeinstallprompt. Detect and show custom UI:
function checkIOSInstall() { const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); const isStandalone = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
if (isIOS && !isStandalone) { // Show custom "Add to Home Screen" instructions showIOSInstallBanner(); return false; }
return true; // Already installed or not iOS}
function showIOSInstallBanner() { // Show overlay with instructions: // 1. Tap Share button // 2. Tap "Add to Home Screen" // 3. Tap "Add"}EU Digital Markets Act Impact
The EU’s Digital Markets Act may force Apple to allow alternative browser engines on iOS. This could enable:
- Chrome with Blink engine on iOS
- Full PWA support through alternative browsers
But this is EU-only for now, and Apple is fighting implementation.
Summary
In this post, I explained Safari’s PWA limitations on iOS. The key points are:
- iOS Safari lacks background sync, has limited storage, and push notifications only work in iOS 16.4+ for installed PWAs
- All iOS browsers use WebKit, so Chrome/Firefox on iOS share the same limitations
- Use feature detection, server-side backup, and iOS-specific install prompts to work around these gaps
For critical applications requiring full PWA features on iOS, a native app may still be necessary. But for many use cases, careful fallbacks can deliver a good experience.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Apple Safari WebKit PWA Documentation
- 👨💻 web.dev PWA Capabilities
- 👨💻 caniuse.com PWA Features
- 👨💻 EU Digital Markets Act
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments