DEV Community

Cover image for Progressive Web Apps vs Native App: When a PWA Is Enough
Muhammad Moiz
Muhammad Moiz

Posted on Originally published at muhammadmoiz.dev

Progressive Web Apps vs Native App: When a PWA Is Enough

Originally published at muhammadmoiz.dev.

If you are weighing progressive web apps vs native app development, the short answer is this: a PWA is enough when your users mostly work in the foreground, on screens you control, and you need one codebase with fast updates. Go native (or React Native) when you depend on background work, deep hardware access, or iOS features that Safari still does not expose. Below is how to tell which side of that line your product sits on, based on current browser support data and on building an offline-first restaurant POS that runs in the browser.

What is a PWA, in plain terms?

A progressive web app is a website that can behave like an installed app. Technically it is still a web page running inside a browser engine, but it adds two things:

  • A web app manifest: a small JSON file with the app's name, icons, start URL and display mode. This is what lets a browser offer "Install" or "Add to Home Screen".
  • A service worker (optional but common): a script that sits between your app and the network. It can serve cached files when the device is offline and, on some browsers, run tasks in the background.

Once installed, a PWA gets its own icon and opens in its own window without the browser address bar. To the user it feels like an app. Under the hood, the browser is still doing the work, and that is the root of every limitation discussed below.

A native app, by contrast, is built for the operating system directly (Swift/Kotlin, or a cross-platform toolkit like React Native or Flutter that compiles to native components) and is distributed through the App Store or Google Play.

Progressive web apps vs native app: the quick comparison

PWA Native app
Codebase One web codebase for desktop, Android, iOS Separate builds per platform (or a cross-platform framework)
Distribution A URL, plus optional store listings App Store and Google Play review
Updates Deploy to your server, users get it on next load Store review, then users must update
Found by search engines Yes, pages can be indexed Store search only (unless you also have a website)
Offline use Yes, with a service worker and local storage Yes
Background sync on iOS Not supported in Safari Supported via OS APIs
Push notifications on iOS iOS 16.4+, only when added to Home Screen Supported
Bluetooth / USB hardware Chromium browsers only, not Safari Supported
Custom install button on iOS Not supported Not applicable (store install)

The rows that matter most are the bottom four. Everything above them is where PWAs usually win.

What PWAs can't do on iOS (as of November 2026)

Most "PWA vs native" decisions are really "how much do we care about iPhone users?" decisions. Android with Chrome supports far more of the web platform than iOS does. I checked MDN's browser compatibility data in November 2026, and these are the gaps that most often push a project toward native:

Push notifications need a Home Screen install

Safari on iOS added the Push API in version 16.4, but MDN notes it only works for web apps saved to the Home Screen. A user who just visits your site in Safari cannot get push messages. That means your onboarding has to talk people through "Share, then Add to Home Screen" before notifications even become possible.

No custom install prompt

On Chrome and Edge, your app can listen for the beforeinstallprompt event and show its own "Install app" button at a sensible moment. Safari does not support that event, and MDN states plainly that this technique does not work on iOS. Installing is entirely manual for iPhone users. Since iOS 16.4, they can at least do it from the Share menu in Safari, Chrome, Edge, Firefox and Orion, not only Safari.

No background sync or background fetch

The Background Synchronization API lets a service worker retry a failed request once the connection returns, even after the user has closed the tab. Periodic Background Sync and Background Fetch go further. According to MDN's compatibility data, Safari supports none of these. On iOS, your app can only sync while it is open.

No Bluetooth, USB or serial hardware access

Web Bluetooth, WebUSB and Web Serial exist in Chromium browsers but not in Safari. If your product needs to talk to a card reader, label printer, scale or other peripheral from an iPhone or iPad, a PWA alone cannot do it.

Smaller gaps

  • Badging (the number on the app icon) works on iOS 16.4+ for Home Screen web apps.
  • Screen Wake Lock (keeping the screen on) arrived in Safari 16.4, but MDN notes it did not work in Home Screen web apps until iOS 18.4.
  • Vibration is not supported in Safari at all.

Check the EU caveat: Historically every iOS browser had to use WebKit, so Chrome on iPhone had Safari's limits. MDN notes that since iOS 17.4 Apple allows other browser engines in the EU, so behaviour there can differ. Test on the devices and regions your customers actually use.

Offline storage: how much data can a PWA keep?

Offline-first apps live or die on local storage, so this deserves its own section. Small key-value data can go in localStorage, which is capped at about 5 MiB per origin. Anything serious (orders, products, customers) belongs in IndexedDB, usually through a library rather than the raw API.

MDN's storage guide gives the current quota rules:

  • Chrome and Edge: an origin can use up to 60% of total disk size.
  • Safari (macOS 14 and iOS 17 onward): around 60% of total disk for browser apps and Home Screen web apps, and around 15% when the site runs inside another app's embedded web view.
  • Firefox: in best-effort mode, the smaller of 10% of the disk or a 10 GiB group limit.

The bigger risk is not quota, it is eviction. By default, browser data is "best-effort", meaning the browser may delete it under storage pressure. Safari goes further: with cross-site tracking prevention on, it removes script-created data for origins the user has not interacted with in the last seven days of browser use. When eviction happens, the whole origin's data goes at once.

Two practical defences:

// Ask the browser to treat this origin's data as persistent.
// Chrome and Safari decide silently based on how the user engages with the site;
// Firefox shows a permission prompt.
export async function requestDurableStorage(): Promise<boolean> {
  if (!navigator.storage?.persist) return false;
  const alreadyPersisted = await navigator.storage.persisted();
  if (alreadyPersisted) return true;
  return navigator.storage.persist();
}

// Show the user (or your support team) how close the app is to its limit.
export async function storageReport(): Promise<string> {
  if (!navigator.storage?.estimate) return "Storage estimate not available";
  const { usage = 0, quota = 0 } = await navigator.storage.estimate();
  const pct = quota ? ((usage / quota) * 100).toFixed(1) : "?";
  return `Using ${(usage / 1_048_576).toFixed(1)} MB of local storage (${pct}% of quota)`;
}
Enter fullscreen mode Exit fullscreen mode

And the rule that matters more than any API call: local data must never be the only copy of anything important. Sync it to a server as soon as a connection is available, and design the app so a wiped device can rebuild itself from the server.

A barista in an apron using a tablet at a wooden café counter

Photo: Nathan Dumlao on Unsplash

Lessons from an offline-first POS that runs in the browser

I spent about two years as a senior frontend engineer on Oscar, a point of sale system for restaurants and retail in Pakistan. It is a React web app, not a store app, and it had to keep taking orders, printing receipts and sending tickets to the kitchen even with the internet down. A few things that experience taught me about when the web is enough:

The browser handled offline data well. Oscar keeps its data in a local WatermelonDB database on browser storage, so the POS works the same with or without a connection, and nobody has to install anything. Changes sync to a Django backend when the connection returns, and the server stays the source of truth for reporting. I wrote more about that architecture in Offline-First POS: Lessons From Building Oscar in React.

Real-time features need an offline plan of their own. Orders reached the kitchen display system over WebSockets. Every feature like that needs a decision, made at design time, about what happens when the socket drops.

Hardware was the hard part. Restaurants need receipt, kitchen and bar printers. Oscar connects to local printers through QZ Tray, a printer bridge, and I built the routing so each ticket lands on the right printer: receipts at the counter, tickets in the kitchen, drinks at the bar. That pattern (a web app plus a local helper for hardware) is a useful middle ground, but it is one more component to set up and support.

The broader lesson: Oscar ran on counters and devices the business controlled, in the foreground, all shift long. That is the ideal case for a web app. A consumer app that must wake up in the background on a stranger's iPhone is the opposite case.

When a PWA is enough: a checklist

Answer these honestly. If most of your answers land on the left, a PWA (or a plain responsive web app) is probably the right first build.

  1. Do users work with the app open? Dashboards, POS screens, booking tools, internal tools and B2B SaaS are used in the foreground. A PWA fits. Apps that must react while closed (trackers, messengers with guaranteed delivery) lean native.
  2. Who owns the devices? If you control the hardware (counter tablets, staff laptops, Android devices), you can standardise on Chrome and get the full PWA feature set. If the audience is mostly iPhone consumers, plan around the iOS gaps above.
  3. Do you need peripherals? Printers, scanners, card readers and Bluetooth devices push you toward native, a cross-platform app, or a local bridge like the Oscar setup.
  4. How important are push notifications? If they are core to retention and your users are on iPhone, the "add to Home Screen first" step will cost you opt-ins.
  5. Does discovery come from Google or from the app stores? PWAs are web pages, so they can rank in search and be shared as a link. Store presence matters more for some consumer categories. You can also wrap a PWA for some stores (MDN points to tools like PWABuilder), but check each store's rules first.
  6. How often will you ship? Web deploys reach everyone on the next load. Store apps add review time and update lag.
  7. What is the budget? One web codebase is usually less work than two native apps. React Native narrows that gap if you need native features.

What this means for founders and app owners

For most early-stage products, start on the web. A well-built responsive web app with a manifest and a service worker covers desktop, Android and most iPhone use, can be found on Google, and costs less to build and maintain than separate native apps. If you hit a real platform wall (background work, hardware, iOS push at scale), you can add a React Native app later and reuse your backend, API and much of your business logic.

The mistake to avoid is choosing a PWA and then discovering the iOS gaps after launch. Write down the device features your product depends on, check each one against current browser support, and prototype the riskiest one first.

If you are planning an offline-first app or a POS and want a second opinion on web vs native, take a look at my product development service or the React development service, or see how the Oscar POS case study handled it.

Sources


I'm Muhammad Moiz, a full-stack developer who builds web apps, SaaS and POS systems, and takes AI-built apps (Lovable, Bolt, Replit) to production. Get in touch.

Top comments (0)