Design the billing and entitlement platform for an app with iOS, Android and web subscriptions and a backend API.

28.6.2 · L8 · Interview

Mental model. Think of a bank ledger: every store event is a signed transaction slip, the balance (entitlement) is derived from the slips, and an audit can always recompute it.

Core idea: one entitlement service, many payment sources. Each store is an ingestor that turns its own events into a normalised internal event (GRANTED, RENEWED, GRACE, EXPIRED, REVOKED, with an external transaction id, product mapping, price and period). For Apple: a notifications endpoint (verify the JWS and chain, deduplicate by notificationUUID, enqueue, return 200), client-submitted transaction JWS verified on arrival (so the user sees access instantly), and a scheduled reconciliation job that calls the Server API for subscriptions whose state looks stale. Google Play (Real-time developer notifications plus the Play Developer API) and web (Stripe or similar webhooks) get the same treatment. Map store purchases to your user with appAccountToken (Apple) and obfuscated account ids (Google), and handle the case where the purchase arrives before the account exists (a pending claim table).

Storage and reads. Keep an append-only event log (the audit trail and the way to replay after a bug) and a projection table of current entitlements per user (tier, expiry, source, grace flag), derived by a pure function of the events as in the earlier questions and rebuildable at any time. Clients read the projection through your API (cached, short TTL), and still derive from StoreKit locally for instant UX; the server wins on conflict. Handle: duplicate and out-of-order events (idempotency keys, source timestamps), refunds and revocations (and consumable clawback policy), family sharing, price changes and consent, cross-platform double subscriptions (offer to cancel one), account deletion and privacy (keep what tax and fraud rules require), key rotation for the App Store Server API keys and webhook certificates, rate limits and backoff on API calls, environment separation (sandbox never grants production features), and observability (webhook lag, verification failures, mismatches between client and server state, MRR and churn reports built from the event log). Failure modes to design for: Apple outage (serve cached entitlement, extend a grace window), a bad deploy that mishandles one event type (replay from the log), and a flood of renewals at month end (queue and scale consumers). Nothing here needs a specific vendor, and a managed layer such as a subscription-management service can replace the ingestors if the build cost is not worth it; the trade-off is control and fees versus time.

Common traps

  • Trusting the client's claim of entitlement. The client shows UX; the server projection is the authority for server-backed features.
  • Overwriting state instead of appending events. You lose the audit trail and cannot replay after a bug.

They might follow up with

  • Build or buy? Buy if a few platforms and little custom logic; build when pricing, entitlement or compliance rules are core.
  • How do you test it? Replay recorded notification sequences, including duplicates and reordering, against the reducer and compare projections.

Related questions

  • 28.4.3 How do App Store Server Notifications V2 behave, and how do you process them idempotently and out of order?
  • 28.4.4 How do you authenticate to the App Store Server API, and what do you use it for?
  • 28.3.1 How do you compute what a user is entitled to, and which transactions are excluded from…
  • 28.6.1 What do App Review rules require for digital goods and subscriptions, and how do external purchase links and…
  • 12.5.1 How should a client retry failed requests: what to retry, how long to wait, and what idempotency has to do…
  • 26.1.4 Design a shopping app with cart and checkout: catalogue, cart merging, price authority, payment, idempotency…

← What do App Review rules require for digital goods and subscriptions…