In-app purchases look simple from the outside — tap, pay, unlock — but the implementation underneath involves platform cuts, receipt validation, and edge cases that quietly break revenue if handled carelessly.
In-app purchases look simple from the outside — tap a button, pay, unlock something. Underneath, the implementation involves platform revenue cuts, server-side receipt validation, subscription lifecycle states that most teams underestimate, and a handful of edge cases that quietly break revenue reporting if they aren't handled deliberately. Getting the surface interaction right is the easy 20%; getting the lifecycle right underneath it is the harder 80% that actually determines whether the monetization model works.
Understanding the Platform Economics First
Both Apple and Google operate their in-app purchase systems as mandatory payment processors for digital goods and subscriptions sold within apps on their platforms — you generally can't route around them for digital content, though physical goods and services consumed outside the app are typically exempt. Both platforms take a standard commission, historically around 30% on the first year of subscription revenue, often dropping to a lower rate (around 15%) for subscriptions retained past twelve months, and both offer a reduced-rate small business program for developers under a certain annual revenue threshold. These percentages and thresholds shift periodically, so the current numbers should always be checked against Apple's and Google's own developer documentation before pricing decisions are finalized — treat the ballpark figures here as general orientation, not a locked-in rate.
This matters for pricing strategy from day one: whatever price point you settle on needs to account for the platform's cut being taken off the top, not layered on top of your target margin.
Choosing a Monetization Model
Three broad models cover most mobile apps, and the right choice depends on the nature of what you're selling:
- One-time purchases — a single payment unlocks a feature, a piece of content, or removes ads permanently. Works well for utility apps, one-off content (a course, a book), or simple pro-feature unlocks.
- Subscriptions — recurring payment for ongoing access, typically monthly or annual. Works well when the app delivers ongoing value that renews — content libraries, SaaS-style tools, services with continuous usage.
- Freemium with a paywall — a free tier that demonstrates value, with premium features gated behind a subscription or purchase. This is the dominant model for consumer apps today because it lets users experience real value before being asked to pay.
Many successful apps blend these — a free tier, a subscription for full access, and occasional one-time purchases for specific add-ons. The model should follow from how your app delivers value, not from what's currently fashionable in app store trends.
Technical Implementation: The Core Pieces
On iOS, this means integrating with StoreKit (StoreKit 2 is the modern approach, offering cleaner async/await APIs and built-in transaction verification compared to the original StoreKit). On Android, it means integrating with the Google Play Billing Library. Both require:
- Product configuration in App Store Connect and the Google Play Console — defining product IDs, prices per region, and subscription groups/tiers before any client code can reference them.
- Purchase flow handling — initiating the purchase, handling the platform's native payment sheet, and responding to success, cancellation, and failure states gracefully in the UI.
- Receipt or transaction validation — verifying that a purchase is genuine before unlocking content. This should happen server-side, not just on-device, because client-side-only validation is straightforward to bypass with modified app builds or intercepted traffic.
- Entitlement management — a server-side record of what each user account is actually entitled to, kept in sync with the platform's subscription status rather than relying solely on local device state, which can become stale or be manipulated.
The server-side validation and entitlement layer is the part most commonly under-built, and it's also the part where revenue leakage and support tickets both concentrate when it's skipped.
Handling the Subscription Lifecycle Properly
A subscription isn't a single event — it's a lifecycle with several states that the app needs to handle correctly:
- Restore purchases. Users reinstall apps, switch devices, or get new phones constantly. A visible, working "restore purchases" flow is both an App Store requirement on iOS and a basic expectation users have — its absence generates a disproportionate volume of support complaints relative to how simple it is to implement correctly.
- Upgrades and downgrades between tiers. If you offer multiple subscription tiers, users need a clear path to move between them, and the billing system needs to handle proration (crediting unused time from the old tier) correctly rather than double-charging or losing paid-for time.
- Grace periods and billing retry. When a renewal payment fails — an expired card, insufficient funds — both platforms offer a grace period during which the user keeps access while the platform retries the charge. Apps should honor this state rather than immediately cutting off access on the first failed payment, since a meaningful share of these failures self-resolve on retry.
- Dunning and win-back communication. Beyond what the platform handles automatically, proactively notifying users before a renewal, and having a clear (simple, not aggressive) win-back message after a cancellation, measurably improves retention over doing nothing.
- Cancellation handling. Cancellation happens through the platform's own subscription management, not through custom in-app flows on iOS — apps that try to build their own cancellation UI instead of directing users to platform settings frequently run into App Store review rejections.
Paywall Placement and Pricing Psychology
Where and when a paywall appears matters as much as what it says. A few patterns that consistently perform better than a paywall shown immediately at first launch:
- Let users experience real value first. A paywall shown before a user has done anything in the app converts far worse than one shown after they've hit a genuine moment of value or a natural usage limit.
- Trials reduce the decision friction of the first payment, but the trial-to-paid conversion depends heavily on whether users actually reach the "aha" moment during the trial window — a trial that's too short to demonstrate value converts poorly regardless of the discount offered.
- Annual pricing framed as a monthly-equivalent ("billed annually, equivalent to $X/month") typically converts better than presenting the annual price as a single large number, even when the underlying cost to the user is identical.
- Clarity beats cleverness. Users should be able to tell, at a glance, exactly what they're paying, how often, and what they get. Paywalls that obscure pricing or auto-select the most expensive tier by default tend to generate refund requests and app store review flags, both of which cost more than the marginal revenue gained.
Server-Side Infrastructure: Webhooks and Revenue Reporting
Both Apple and Google offer server-to-server notification systems (App Store Server Notifications and Google Play's Real-Time Developer Notifications, respectively) that push subscription lifecycle events — renewals, cancellations, refunds, grace period entry, billing recovery — directly to your backend as they happen, rather than requiring your app to poll or wait for the client to check in. Building against these notifications, rather than relying solely on the client app to report its own subscription state, is what actually keeps a server-side entitlement record accurate in near real time.
This matters most in the cases that cause the most support friction: a user cancels on one device but the app on their other device still shows them as subscribed, or a refund is issued and access needs to be revoked promptly rather than whenever the user next opens the app and triggers a client-side check. Systems built without this webhook layer tend to work fine in the common case and fail unpredictably in exactly these edge cases, which is also where the angriest support tickets originate.
Beyond real-time status, most teams also need a clearer view of subscription health than App Store Connect or the Play Console provide out of the box — metrics like trial-to-paid conversion rate, monthly recurring revenue, churn by cohort, and revenue by acquisition source usually require either a dedicated subscription analytics tool or custom reporting built on top of the server-side entitlement data already being tracked. Getting this instrumented early matters because subscription businesses are won or lost on retention and conversion trends that only become visible with a few months of consistent data — trying to reconstruct this history after the fact, from platform dashboards alone, is far harder than tracking it from day one.
Common Pitfalls That Cause Real Problems
A few implementation mistakes show up repeatedly and are worth checking for explicitly:
- Testing only in sandbox, never validating production edge cases — sandbox environments on both platforms behave differently from production in subtle ways (accelerated renewal timers, different receipt formats), and a purchase flow that works perfectly in sandbox can still surface bugs at real-world scale.
- Client-only entitlement checks — relying on local app state to decide what a user can access, rather than checking against a server-side record, opens the door to both legitimate sync bugs (a user who paid but the app doesn't reflect it) and outright bypass.
- No handling for refunds — both platforms allow users to request refunds, and the app's entitlement system needs to react to a refund notification by revoking access, not just leave it granted indefinitely.
- Ignoring regional pricing differences — a price that feels reasonable in one market can be wildly out of line in another; both platforms support per-region pricing, and using flat USD-equivalent pricing everywhere often hurts conversion in price-sensitive markets without meaningfully helping revenue.
Disclosure and Compliance Basics Worth Getting Right
Both app stores, and in many regions the underlying consumer protection law, require clear disclosure of subscription terms before a user pays: what's being charged, how often, whether it auto-renews, and how to cancel. This isn't a Scult-specific or app-specific certification — it's a baseline expectation both platforms enforce during app review, and getting it wrong is one of the more common causes of app store rejection for apps with a subscription model. Practically, this means the paywall screen itself should state the price, billing frequency, and auto-renewal terms in text a user will actually read, not just in a linked terms-of-service document, and the cancellation path should be genuinely easy to find rather than buried.
Getting in-app purchases right is less about the purchase button itself and much more about everything that has to keep working correctly afterward — renewals, restores, refunds, upgrades — often for years after the original transaction. At Scult, when we build monetization into a mobile app under our Mobile App Development service, the server-side entitlement and lifecycle handling gets built alongside the purchase UI from the start, precisely because retrofitting it after launch is far more expensive than building it correctly the first time.



