Mobile App Subscriptions: How Apple and Google Billing Actually Works

If you want to charge users for ongoing access to your mobile app, you're going to encounter one of the more technically demanding areas of mobile development. In-app subscriptions look simple from the outside — user subscribes, user gets access, user gets charged every month. In practice, you're dealing with two separate billing platforms, server-side validation requirements, a dozen subscription lifecycle states, and edge cases that will surface at the worst possible times.
This article explains how the systems actually work, where the complexity lives, and what you can do to manage it without building a billing infrastructure from scratch.
Why Mobile Subscriptions Are Hard
The core problem is that you're not building one subscription system — you're building two. Apple's In-App Purchase (IAP) and Google Play Billing are entirely separate systems with different APIs, different client libraries, different webhook formats, different terminologies, and different edge cases.
Both systems require that subscription state be validated on your server, not just on the device. You cannot trust the device to tell you whether a subscription is active — devices can be jailbroken, receipts can be tampered with, and client-side state can get out of sync. Every purchase must be verified server-side before granting access.
Both systems also send server-to-server notifications (webhooks) when subscription events occur: new subscriptions, renewals, cancellations, billing failures, refunds. If you don't have a server listening to and processing these webhooks correctly, your subscription state will drift. Users who cancel will keep access. Users who get refunded will keep access. Users whose billing retries eventually succeed won't have their access restored promptly.
This is why subscription implementation is its own project phase, not a feature you bolt on at the end. It also has a direct impact on how much your app costs to build — budget 2–4 weeks of focused development time for this work alone.
Apple In-App Purchase: Key Concepts
Apple's system uses specific terminology that differs from standard SaaS subscription concepts.
Subscription Groups. Your auto-renewable subscriptions must belong to a Subscription Group. A user can only hold one active subscription per group at a time. This is how you model upgrade/downgrade — put your monthly and annual plans in the same group.
Original Transaction ID. Every subscription has an original transaction ID that persists for the lifetime of the subscription, even through renewals, upgrades, and resubscribes. This is the stable identifier you use on your server to track a user's subscription history.
App Store Server Notifications (ASSN). Apple's webhook system sends events to your server URL. Version 2 (V2) notifications are the current format — JSON Web Signature (JWS) signed payloads. You must configure this URL in App Store Connect. Key events to handle: SUBSCRIBED, DID_RENEW, DID_FAIL_TO_RENEW, GRACE_PERIOD_EXPIRED, EXPIRED, REFUND, REVOKE.
Billing Grace Period. When a renewal fails (card decline, etc.), Apple enters a grace period (configurable from 3 to 16 days depending on subscription duration) during which your app should continue granting access. Apple retries billing silently during this period. If you cut off access during grace period, you will lose users who would have renewed if their card had just been updated.
StoreKit 2. The current native API for iOS IAP. Uses async/await, is much cleaner than the original StoreKit, and has a proper transaction listener model. If you're building a new app in 2026, use StoreKit 2.
Google Play Billing: Key Concepts
Google's system has different terminology for similar concepts.
Purchase Tokens. Instead of transaction IDs, Google uses purchase tokens — opaque strings that represent a purchase. A subscription has one purchase token per billing period; when a subscription renews, a new purchase token is linked to the original via the linkedPurchaseToken field. You must follow the token chain on your server to correctly track subscription history.
Real-time Developer Notifications (RTDN). Google's webhook system publishes subscription events to a Google Pub/Sub topic, which you subscribe to. This is a different architecture than a simple HTTP POST — you need a Pub/Sub subscriber endpoint. Events include: SUBSCRIPTION_PURCHASED, SUBSCRIPTION_RENEWED, SUBSCRIPTION_IN_GRACE_PERIOD, SUBSCRIPTION_ON_HOLD, SUBSCRIPTION_CANCELED, SUBSCRIPTION_REVOKED, SUBSCRIPTION_EXPIRED.
Account Hold and Pause. In addition to grace period (which Google also supports), Google has "account hold" (payment declined, access suspended) and "pause" (user-initiated subscription pause). These states don't exist in Apple's system. Your server must handle them.
Play Billing Library 7. The current Android client library. Google updates this frequently and enforces minimum version requirements in the Play Store. Running an outdated billing library version will get your app removed from the Play Store.
What RevenueCat Solves
RevenueCat is a subscription management platform specifically built to abstract Apple IAP and Google Play Billing behind a single SDK and API. Most professional mobile teams use it for subscription-heavy apps, and for good reason.
What you get with RevenueCat:
- Single SDK on the client. Purchases.shared.getCustomerInfo() works identically on iOS and Android.
- Unified entitlements model. You define entitlements (e.g., "pro_access") and map them to products from both stores. Your app checks entitlements, not platform-specific purchase state.
- Server-side validation handled for you. RevenueCat validates receipts with Apple and Google and maintains accurate subscription state on their servers.
- Webhook relay. RevenueCat sends unified webhook events to your backend — one format, regardless of platform. You handle initial_purchase, renewal, cancellation, billing_issue, etc. — not platform-specific events.
- Dashboard. MRR, churn, cohort analytics, individual subscriber lookup. Useful for debugging and for understanding subscription health.
RevenueCat pricing: Free up to $2,500 Monthly Tracked Revenue. After that, 1% of revenue. For most apps, this is worth it. The alternative is building and maintaining your own webhook processors, receipt validators, and subscription state machine for both platforms — that's weeks of engineering time and an ongoing maintenance burden.
RevenueCat doesn't eliminate the complexity — it handles it for you. You still need to understand the underlying systems well enough to configure it correctly and debug edge cases.
If you run web-based subscriptions via Stripe alongside your mobile app, note that Apple and Google do not allow you to direct users to pay through your website to avoid their billing systems — any digital goods or services sold in-app must go through IAP.
Server-Side Validation: Why It's Not Optional
The device tells your backend it has an active subscription. Your backend needs to verify this with Apple or Google before granting access. This is not optional.
With Apple: your server calls the App Store Server API using a signed JWT (your private key from App Store Connect) to retrieve transaction information. With RevenueCat, they handle this and expose it via their REST API.
Without server-side validation: any user can intercept the purchase confirmation and replay it, or share screenshots of receipts. This is a real attack vector, not a theoretical one.
The Most Common Subscription Implementation Bugs
After building subscription-enabled apps, these are the patterns that cause the most production issues:
- Not handling grace period. Revoking access the moment a renewal fails. Apple and Google both have grace periods. Users in billing retry should retain access.
- Not following Google's linkedPurchaseToken chain. When a Google subscription renews, the new token has a linkedPurchaseToken pointing to the previous one. If your server doesn't resolve this chain, you'll create duplicate subscription records and misread subscription state.
- Assuming the purchase is complete client-side. The client StoreKit or Play Billing callback says success. Your server never validates. User gets access. Three weeks later you find out 10% of "subscriptions" are invalid.
- Not handling SUBSCRIBED vs DID_RENEW correctly on Apple. First purchase and renewal are different events. Handle both.
- Missing the free trial to paid conversion webhook. If you offer a free trial, the DID_RENEW event fires when the trial converts to a paid subscription. If you're not listening to it, you won't know the user is now a paying subscriber.
Not testing billing edge cases before launch. Apple's sandbox environment and Google Play's test purchases let you simulate renewals, cancellations, billing failures, and refunds. Every subscription edge case should be tested in sandbox before submission. The App Store submission process also requires that subscription terms are clearly disclosed — a common rejection reason for subscription-based apps.
Plan for This Before You Build
Subscription implementation affects your data model, your API design, your webhook infrastructure, and your App Store submission. It's not something you add at the end.
If your app will include subscriptions, make sure your technical discovery phase explicitly scopes the subscription system — both platforms, server-side validation, webhook handling, entitlement model, and edge case behavior.
Our technical discovery engagement covers this in detail before a line of code is written.
Learn about our mobile app development service or reach out to discuss your project.
For the full picture of what goes into a mobile build, see our complete mobile app development guide.
Related Posts

Mobile App Development: The Complete Guide for Non-Technical Founders
Everything you need to know before building a mobile app — platform choice, costs, timelines, App Store approval, subscriptions, and finding the right team.

How to Add Subscription Products to Your E-Commerce Store
Subscription e-commerce is more complex than standard checkout. Here's how recurring billing, free trials, pauses, and cancellations actually work — and what to build.