Article

PWA or native for a commerce app

Kreshnik Rraci ·

Ask whether a shopping app should be native or a Progressive Web App and the argument immediately becomes a list of capabilities: native can do NFC, native has better push, native feels smoother. All true, and mostly beside the point. For a commerce product the decision is made by two other things - how people arrive, and how often you ship - and both favour the web until a specific, recognisable condition changes.

The problem: the download is the funnel

A shopping app has a conversion funnel like any other, and it starts earlier than the first screen. It starts at the moment someone decides to look.

For a store-listed app that moment is followed by: open the store, search, find the right listing, tap install, wait for a download that is routinely 50-150 MB, wait for it to unpack, open it, grant permissions, and finally see a product. Each step loses people. On a metered connection or a mid-range phone with 2 GB free, "wait for the download" alone can lose most of them.

For a web app the same moment is followed by: tap the link, see the product. Installation - if it happens at all - comes after the person has already found something they want, which is the only moment they're motivated to do it.

That asymmetry matters more for commerce than for almost any other category, because the people you most want to convert are the ones with the least patience: a shopper who saw a store on social media, a customer who scanned a QR code at a till, someone who was sent a link by a friend. None of them are browsing an app store. They arrived through a link, and a link is the web's home turf.

The options

There are really three, not two.

PWA Wrapped web (TWA / Capacitor) Native (Swift / Kotlin, or React Native)
How users arrive Any link, QR, share, search result Store listing and any link Store listing only
Install friction None to see it; optional afterwards Store download, but small (it's a shell) Store download, full size
Ship a fix Next page load. Minutes Web content: minutes. Shell: store review Store review: hours to days, per platform
Codebases One One, plus a thin shell per platform Two, or one with a platform layer
Offline App shell and cached reads; queued writes need building Same as PWA Same work, different APIs
Push Chromium: yes. iOS: yes for installed apps since 16.4 Yes, via the shell Yes
Hardware access Camera, geolocation, share, badging; limited NFC/BLE, no background location PWA set plus what the shell bridges Everything the platform allows
Discovery via store search No Yes Yes
Platform fee on physical goods None None None - IAP rules apply to digital goods, not physical ones
Team Web engineers Web engineers plus a little platform work Platform engineers, per platform

Two rows deserve emphasis because they're the ones people get wrong.

"Ship a fix" is the row that decides most of this. A bug found at 09:00 in a web app is fixed for every user at 09:20. In a store-listed native app it is fixed when review clears and users update - hours at best, days at worst, and never for the users who don't update. For a product that is changing weekly, that difference compounds into a different development process, not just a different deploy step.

The platform-fee row is a common misconception. Apple's and Google's in-app-purchase requirement, with its 15-30% cut, applies to digital goods and services. Selling physical goods - groceries, clothes, anything delivered - uses your own payment provider in any of the three options. A commerce app is not choosing the web to dodge the fee; there is no fee to dodge.

The path from intent to first product view for a store-listed app versus a web app STORE-LISTED APP open store search, find download50-150 MB open, permit see a product five steps before value · each one loses people · the biggest loss is the download WEB APP tap the link see a product install, optionallyafter they want it one step before value · installation moves to the moment the person is motivated a fix ships on the next page load, on both paths, to everyone
The download is the funnel. The web path puts value first and installation last; the store path does the reverse.

The pattern: web first, wrap on a gate, go native for a reason

The recommendation for a commerce product, from launch onward:

1. Build it as a PWA. One codebase, reachable by link, fixes shipped in minutes. Do the parts that make it feel installed properly: a manifest with display: standalone, real icons, shortcuts for the two or three things people do most, and screenshots so the install prompt shows what they're getting. A service worker for the shell and cached reads - and a deliberate write-side design for anything that must work without a connection.

2. Wrap it when a specific gate appears - not before. The gate is one of: we need a store listing for discovery, we need a capability the browser doesn't expose, or a partner requires a store presence. A Trusted Web Activity on Android lists the same PWA in the Play Store with essentially no new code. Capacitor or an equivalent shell does the same for iOS and adds a bridge for native capabilities. The web app stays the product; the shell is packaging.

3. Go native only when the product is capability-bound. If the core of the experience depends on hardware the web can't reach - background location for a courier, NFC payment terminals, BLE scanners on a warehouse floor - the platform layer isn't packaging any more, it's the product. That's a different app with a different team, and it's usually a companion to the commerce app rather than a replacement for it.

Three tiers: what a PWA does on its own, what a wrapper adds, and what only native gives you PWA - the product install · standalone · shortcuts · offline shell · push · camera · geolocation · share · badging start here Wrapped - the same product, packaged store listing (TWA / Capacitor) · bridged capabilities · one codebase kept move here on a gate: store discovery, a partner requirement, one missing API Native - what only the platform can do background location · NFC / BLE hardware · deep OS integration when a capability is the product - often a companion app for a specific role each tier keeps the one above it - going down adds packaging or capability, never replaces the web app
Tiers, not a fork. Most commerce apps live in the top one; the gates that move them down are specific and recognisable.

The mechanics that make the PWA tier hold up

Make installation earn its moment. Chromium fires beforeinstallprompt; capture it, suppress the default, and show your own prompt after a signal of intent - a second visit, an item added to a cart, an order placed. An install banner on first load is the web's version of asking for notification permission before saying hello. On iOS there is no prompt event; the path is Share → Add to Home Screen, and it's worth a short in-app hint at the same intent moments.

Treat the manifest as product surface, not metadata. shortcuts become the long-press menu on the installed icon - the two or three actions people repeat. screenshots with form_factor turn the install dialog from a permission box into a preview. display_override with window-controls-overlay makes the desktop install look like an application rather than a tab.

Push is available on both platforms, with one condition on iOS. Since iOS 16.4, web push works for apps added to the Home Screen; it does not work in the browser tab. So on iOS, installation is the gate to push - one more reason to ask for installation at a moment of intent rather than on arrival.

Plan for storage being evicted. Browsers can clear an origin's storage under pressure, and Safari is more aggressive for sites it considers unused; installed apps are treated more generously. Anything that matters lives on the server. The service worker cache and IndexedDB are accelerators, not the record.

Get the Play listing almost for free. A Trusted Web Activity is a store listing that opens your PWA full-screen with no browser chrome, verified by a Digital Asset Links file on your domain. The app in the store is a few kilobytes; the product is still the website. Updates never go through review.

The trade-offs

You give up store discovery. Some people do find shopping apps by searching the App Store. If that is a meaningful acquisition channel for your category, the wrapper tier exists precisely to recover it - on Android for near-zero cost, on iOS for a modest shell. It is a trade you can revisit, not a door that closes.

iOS is the less generous platform for web apps, and it decides the terms. No install prompt event, push only when installed, stricter storage policy, and periodic changes in what installed web apps are allowed to do. Every one of these has a workable answer today; none of them is under your control. A product that leans hard on iOS-specific behaviour should keep the wrapper option warm.

Some capabilities are simply absent. Background geolocation, most NFC and Bluetooth, contacts, telephony, deep OS integration. If one of these is central, you're in the native tier and should know it early. For a shopper - browse, search, cart, pay, track - none of them are.

"Feels native" is real, and it's work. A PWA that scrolls badly or animates on the main thread feels like a website in a box, and shoppers notice. The performance budget is part of the design, not a follow-up: transform and opacity only, content-visibility on long lists, no layout thrash on scroll. This is the same discipline a native app needs; the web just gives you more ways to skip it.

When it flips

Checklist

  1. Where do our users actually arrive from - links and QR codes, or store search? Do we have numbers, or an assumption?
  2. How often do we ship? Would a review queue between us and our users change how we work?
  3. Which capabilities are load-bearing for the shopper, as opposed to for staff, couriers or admins?
  4. Are we selling physical goods? (Then platform IAP rules don't apply, and the fee argument is moot in every direction.)
  5. Does the manifest carry shortcuts, screenshots and a standalone display - or is it a placeholder?
  6. Do we ask for installation and push at a moment of intent, or on arrival?
  7. What's our answer for the iOS constraints, and which one would hurt most if it tightened?
  8. If a gate appears, do we know which wrapper we'd reach for, and have we kept the codebase in a shape that makes that a packaging job?

For a marketplace people reach through a link, the web is not the compromise option. It's the one that puts the product in front of them before asking for anything - and the shape that keeps every other option open.