There are entire sectors that deliver their mobile product through Safari’s Share menu rather than the App Store.

Not because someone on the team read a blog post about progressive web apps and got enthusiastic, but because the store review guidelines make a native build impractical or impossible.

That distinction matters if you run the infrastructure, because every constraint the store would have handled becomes yours. Distribution, caching, update strategy, offline behaviour and notification delivery all land on your stack.

Why Some Industries Ship PWAs Instead of App Store Builds

The Store Rules That Push Delivery to the Web

Apple’s App Review Guidelines put gaming, gambling and lotteries under section 5.3, and the operative clause is 5.3.4.

Apps offering real money gaming must have the necessary licensing and permissions in the locations where the app is used, must be geo-restricted to those locations, and must be free on the App Store.

Read that as an engineering requirement rather than a legal one. You need a per-jurisdiction licence inventory, enforced geofencing at the application layer, and a distribution footprint that matches both.

Restricting availability in App Store Connect is not sufficient; the app itself has to refuse to operate outside licensed territory.

Guideline 5.3.3 adds a second problem. Apps may not use in-app purchase to buy credit or currency for real money gaming of any kind, and may not initiate fund transfers in the app.

So the one thing the App Store genuinely gives you, a payments system that already works, is unavailable for this category. You are building your own cashier regardless.

Google Play operates a country-by-country allowlist for the same category, with a separate application per market. Broader reach than Apple, still an approval gate per territory.

Stack those together and the calculation changes. Two review processes, per-territory licensing evidence, geofencing you must build anyway, and no access to store payments. The web starts looking less like a compromise and more like the shorter path.

What That Looks Like in Practice?

The effect is visible from the outside. According to Washington City Paper, whose reviewer tested 15 mobile casino brands across iPhone and Android, most US-facing apps never appear in the App Store at all, and the few that do are locked for most players.

Their testing criteria were revealing too: lobbies that load on 4G in seconds, and tap targets a thumb can actually hit.

Both are web performance problems, not native ones, which tells you where the engineering effort actually goes in this category.

The Three Pieces

A PWA rests on three things, and only three.

A service worker, which is a script running on a separate thread acting as a programmable network proxy. It intercepts fetch events and decides whether to answer from cache or hit the network.

A web app manifest, a JSON document declaring name, icons, start_url, display mode and theme colour. This is what makes the thing installable.

HTTPS, without exception. Service workers will not register over plain HTTP. Localhost is the only carve-out, which is there so you can develop.

Registration is unremarkable:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}

Scope is the part people get wrong. A worker registered at /js/sw.js controls only /js/ and below. To control the whole origin from a script in a subdirectory, send the Service-Worker-Allowed header with the value you need. Otherwise put sw.js at the document root and move on.

Where iOS Constrains You?

This is where planning matters, because the limits are real and mostly undocumented in the places you would look first.

Cache API storage is capped. WebKit documentation puts the Cache API quota at a fixed 50 MB per partition on iOS. Safari 17 did raise broader origin storage limits considerably, up to around 60% of disk for home screen web apps, and added the Persistent Storage API to request protection from eviction. That API requires notification permission to function, which is an awkward coupling.

Eviction is aggressive. A seven-day cap on script-writable storage has applied since iOS 13.4, and Safari uses least-recently-used eviction under storage pressure. Data from a rarely opened origin goes first. Treat the cache as a performance optimisation, not a database.

Storage is partitioned between contexts. Data written while the site runs in a Safari tab is not visible to the same site launched from the home screen. Users who browse first and install later start empty.

There is no install prompt. Apple does not implement beforeinstallprompt, so there is no one-tap banner. Installation is a manual gesture through Safari’s Share menu, and it only works in Safari. Open the same URL inside an in-app webview from a messaging app or ad network and the option is missing or degraded. Getting traffic into Safari is therefore a real funnel decision.

Push works, conditionally. Web Push arrived with iOS and iPadOS 16.4 in March 2023, alongside the Badging API, and it functions only for web apps added to the home screen. A visitor who never installed cannot be reached this way. One operational detail that catches teams out: if your service worker receives a push event and fails to display a notification, iOS cancels the subscription. Always show something.

Guideline 2.5.6 requires every browser on iOS to use WebKit, so switching browsers changes nothing about any of the above.

The EU is a partial exception following the Digital Markets Act, and Apple’s handling of standalone web apps there diverged from iOS 17.4 onward, which is worth checking against current behaviour if you serve European traffic.

Where iOS Constrains You

Serving It Properly From Linux

A few nginx specifics that prevent the common failures.

Never cache the service worker aggressively. If sw.js sits in a CDN or browser cache for a week, your update path is dead:

location = /sw.js {
  add_header Cache-Control "no-cache, no-store, must-revalidate";
  expires off;
}

Serve the manifest with the right MIME type, since some configurations default to text/plain and Safari has historically been particular:

types {
  application/manifest+json  webmanifest;
}

Beyond that, the usual delivery work applies and matters more here than on a conventional site. Brotli over gzip for text assets, HTTP/2 at minimum with HTTP/3 if your CDN edge supports it, AVIF or WebP for imagery, and a hard look at time to first byte.

A lobby that must render on mobile data in a couple of seconds is a budget problem before it is a code problem, and the budget is mostly spent server side.

HSTS is worth enabling properly given the HTTPS dependency. A failed TLS handshake does not degrade a PWA gracefully, it unregisters your delivery mechanism.

When This Is the Right Call?

The honest framing is that a PWA on iOS is a fast front door rather than a full application. Offline browsing, asset caching and installability all work. Background sync, hardware peripherals and reliable long-term local storage do not.

For a product that is fundamentally a fast-loading remote interface with a payment step, that gap costs nothing. For anything depending on device hardware or durable offline state, it is disqualifying.

Which is roughly why the sectors that ship this way ship this way. The store was never going to take them, and the thing they actually needed was a page that loads quickly on a phone.

Willie has over 15 years of experience in Linux system administration and DevOps. After managing infrastructure for startups and enterprises alike, he founded Command Linux to share the practical knowledge he wished he had when starting out. He oversees content strategy and contributes guides on server management, automation, and security.