Subscription Apps on iOS: StoreKit 2 in Practice
StoreKit 2 is Apple's modern subscription API and it changes how iOS apps handle purchases, renewals, and entitlements. Here is what actually matters.
Subscription Apps on iOS: StoreKit 2 in Practice
StoreKit 2 is Apple's subscription API, built natively around async/await and released with iOS 15. It is now the standard for implementing purchases inside an app. It replaces the older model based on SKPaymentQueue with a cleaner transaction verification system, drops the old server side receipt in favor of signed JWS transactions, and adds a subscription status API that makes entitlement checking dramatically more reliable. If you are building a subscription iOS app in 2026, StoreKit 2 is the only path worth taking.
What you need to know
- StoreKit 2 requires iOS 15 or later; if you need to support iOS 14, you must handle both APIs or drop iOS 14 support
- Transaction verification is now done via cryptographically signed JWS tokens, eliminating the unreliable receipt validation model
- The subscription status API gives you a view in real time of a subscriber's current state including cancellations and billing grace periods
- App Store Server Notifications v2 are the companion to StoreKit 2 on the backend and deliver reliable event updates for subscription lifecycle events
- Testing in Xcode's StoreKit sandbox has improved significantly; you can now simulate renewals, cancellations, and billing retry scenarios locally
The core argument
The original StoreKit API was built for a different era of iOS development. Receipt validation required your app to send a receipt blob to Apple's servers, parse an opaque JSON response, and hope the validation did not fail intermittently. Handling subscription renewals, cancellations, billing retries, and family sharing required extensive offline receipt parsing and a lot of defensive programming. Most apps got it wrong in subtle ways. Entitlement bugs were a leading source of subscription support tickets across the industry.
StoreKit 2 fixes the fundamental model. Every transaction is now a signed JWS token that you can verify locally without a round trip to a server, using Apple's public keys. The transaction includes all the information you need: product ID, original purchase date, current subscription state, whether the subscription is in a billing grace period, whether it was purchased through Family Sharing. You get this information in a single call with a clear data model instead of parsing receipt payloads. The async/await API makes the code significantly cleaner than the old model based on delegates, where transaction updates arrived through a shared queue.
The backend story improved too. App Store Server Notifications v2 delivers events in real time for every subscription lifecycle moment: subscription renewed, subscription cancelled, billing retry, grace period started, refund issued. With the original system, you had to poll receipt validation to detect these events. Now Apple pushes them to your server endpoint within seconds of the event. For Nexli, where subscription state needs to be reflected accurately in the user's access permissions, this model of pushing events out is far more reliable than polling and makes the access control logic simpler to reason about.
Common mistakes
- Not verifying transactions on your server for anything sensitive from a security standpoint. StoreKit 2 enables local verification, but for subscription access decisions in a product spanning multiple devices or the web, verify the JWS transaction on your backend. Local verification is convenient for UI purposes; server verification is required for access control.
- Ignoring the billing grace period. Apple gives subscribers a grace period during billing failures before cancelling their subscription. If you revoke access the moment a billing failure occurs, you are cancelling users who Apple will successfully charge within 16 days. Respect the grace period and use it to reduce involuntary churn.
- Not handling family sharing subscriptions. If your subscription supports Family Sharing, members of a family share group can access your app. The entitlement check must account for family sharing, or family members who are legitimately entitled will get an incorrect access denial.
- Not testing subscription scenarios in the Xcode StoreKit sandbox. The sandbox lets you simulate renewals every 5 minutes, test billing failures, test cancellations, and test refunds without real money. If you have not run through every subscription lifecycle scenario in the sandbox before shipping, you have bugs you have not found yet.
- Using StoreKit for subscriptions when the app is primarily a web product. If your primary product runs on the web and the iOS app is a companion, Apple's 30 percent cut on subscription revenue applies to anything purchased through the App Store. Many products route subscription purchases through the web and use the app for delivery only, which is permitted under Apple's current guidelines.
Where to start
Step 1: Configure your products in App Store Connect before writing code. You need the product IDs and subscription group configuration in App Store Connect before StoreKit 2 can load them. This takes longer than expected; allow a day for initial review and approval of your subscription products.
Step 2: Build the entitlement check before the purchase flow. Start with StoreKit.Transaction.currentEntitlements and get the access control working correctly for users who are already subscribed. Subscription status check is the most important piece to get right, more important than the purchase flow itself.
Step 3: Set up App Store Server Notifications v2 on your backend in the same sprint as the iOS implementation. Do not ship a subscription app without notifications from the server. You will miss cancellation events, billing failures, and refunds. These events are what keep your database synchronized with Apple's subscription state.
FAQ
Frequently asked
- Do I need to support the old StoreKit API alongside StoreKit 2?
- How do I handle subscription entitlements for an app that spans platforms?
- What is the App Store's commission on subscriptions?
- How do I test subscription renewals locally?
- Can I offer a free trial with StoreKit 2?
Author
Why you should skip the agency and hire me instead
Agencies markup engineering work by three to five times. Yashveer Singh, founder of Yashveer Labs. I do the work directly. No project manager, no account manager, no overhead. The engineer you talk to is the engineer who writes the code. That changes the math on price, speed, and quality at the same time. If that sounds like the shape of project you have, we should talk.