Design Mobile In-App Purchase and Subscription Validation

Updated · techinterview.org

“Design in-app purchases and subscription validation” is the unglamorous mobile-system-design question that pays for many apps. The interview tests whether you understand the full purchase loop: client APIs, receipt validation, server entitlements, restore flow, family sharing, and the failure modes that produce angry one-star reviews.

Clarify scope

  • One-time purchases, consumables, or subscriptions?
  • iOS, Android, or both?
  • Family sharing supported?
  • Free trials and introductory offers?
  • Server-side entitlements or client-only?

The two stores have different APIs

  • iOS: StoreKit 2 (modern Swift API), StoreKit 1 (legacy callback). Receipts as JWS-signed transactions.
  • Android: Google Play Billing Library v6+. Purchase tokens validated server-side with the Play Developer API.

Universal pattern: client initiates purchase → store processes → client receives signed receipt → server validates with the store → server grants entitlement.

Why server validation is non-negotiable

  • Client-side validation is bypassable (jailbroken devices, modified APKs)
  • Subscriptions need server-tracked state for renewal, cancel, refund
  • Cross-device entitlement requires a server
  • Refund handling requires the server-to-server notification channel

The validation flow

  • Client purchases via StoreKit/Billing API
  • Client receives signed receipt or purchase token
  • Client sends receipt to your server
  • Server validates with Apple’s verifyReceipt endpoint or Google’s purchases.subscriptions.get
  • Server stores entitlement in your DB tied to user account
  • Server responds to client; client unlocks features
  • Server subscribes to App Store Server Notifications / Google Real-Time Developer Notifications for renewal, cancellation, refund

Entitlements model

Server is the source of truth. Schema:

  • user_id
  • entitlement (string identifier, e.g., “pro_monthly”)
  • expires_at
  • auto_renew
  • store_transaction_id (for dedup)
  • last_validated_at

Client checks entitlements at app launch and periodically during use. Cache locally; treat as soft state.

Restore purchases

The user reinstalls or signs into a new device. The “Restore Purchases” button:

  • Calls StoreKit’s currentEntitlements / Billing’s queryPurchasesAsync
  • For each restored receipt, sends to your server
  • Server attaches to the current user account if not already
  • Client receives updated entitlements

Edge case: receipts may be tied to an Apple ID different from your app account. Decide policy (link by Apple ID? require explicit account login?).

Free trials and intro offers

  • Server-side eligibility check before showing trial — Apple/Google enforce one trial per Apple ID/Play account, so don’t mislead
  • Trial state in your DB: trial_started_at, trial_expires_at
  • Renewal at trial end fires through the same notification pipeline

Subscription state machine

  • Pending → Active (initial purchase confirmed)
  • Active → Renewing (auto-renew true)
  • Active → Expiring (user cancelled, still in paid period)
  • Expiring → Expired (period ended)
  • Active → InGracePeriod (billing failed; Apple/Google retry)
  • Active → Refunded (rare; revoke entitlement)

Server tracks state from notifications. Client trusts the server.

Family sharing

  • Apple: enable “Family Sharable” on the IAP product. Apple distributes the entitlement to family members; your validation receives “isFamilyShared” flag
  • Google: similar via Family Library; the purchase token is shared
  • Your server creates entitlements for each family member who installs and validates

Refund handling

  • Apple sends REFUND notification
  • Server revokes entitlement immediately
  • Client checks entitlement on next foreground; loses access without crash
  • Track refund history to detect abuse patterns (some apps deny re-trials to repeat refunders)

Common failure modes

  • Network drops between purchase and server-validate — store the unvalidated receipt locally and retry
  • User logs out before validation completes — receipt orphaned; surface “Restore Purchases” prompt on next login
  • App killed mid-purchase — StoreKit/Billing both replay pending purchases on next launch
  • Server-down during validation — degrade gracefully; trust client receipt for a brief grace window

Compliance considerations

  • Per Apple guidelines, digital goods MUST go through StoreKit; physical goods via your own payment
  • Per the EU DMA, alternative payment methods are allowed in iOS apps in the EU; design for both flows
  • Tax handling — both stores collect VAT/sales tax; your prices include it
  • Subscription terms must be disclosed before purchase; both stores enforce this

What separates senior from staff

Senior candidates discuss server validation and entitlements. Staff candidates discuss the notification-driven state machine, refund handling, family sharing, and the EU DMA alternative-payment flow.

Frequently Asked Questions

Can I store entitlements only on the client?

Possible for one-time purchases on a single device, but you lose cross-device, refund handling, and audit trail. For subscriptions, server-side is required.

What about web-purchased subscriptions?

If you sell subscriptions via your website (Stripe, etc.), grant entitlements server-side and surface them in the app. Apple now allows linking out to the web for purchase in some apps; Google has long allowed it.

Should I use RevenueCat or Adapty?

Many teams do — they handle server validation, notifications, and entitlements. Trade off: less control, monthly fees. For a small team without IAP infrastructure, the time savings are real.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

1972 Soviet postage stamp commemorating the Mars 2 probe

worth a read

Mars For The Rest of Us — a weekly-or-more deep dive on the technical side of Mars exploration: rocket propulsion, microbiology, mission architecture, and everything in between. Written by Maciej Ceglowski.

Read it on Substack
Scroll to Top