โ† All articles

StoreKit 2 vs RevenueCat for Indie iOS Apps in 2026

StoreKit 2 vs RevenueCat for indie iOS apps in 2026: the real cost, working code for both, what iOS 27 changed, and a clear way to choose.

StoreKit 2 vs RevenueCat for Indie iOS Apps in 2026

Every indie iOS developer adding subscriptions hits the same fork: wire up Apple's StoreKit 2 directly, or reach for RevenueCat. It gets framed as native versus third-party, but that framing misses the point. RevenueCat sits on top of the same StoreKit purchase system Apple exposes to you directly, so the real question is not which engine runs the sale. It is how much of the work around the sale you want to build and maintain yourself.

This post compares the two for the case that actually matters to an indie team: shipping a paid iOS app without a backend group to lean on. It covers what each one does, working code for both, the real cost of RevenueCat past its free tier, what iOS 27 changed for subscriptions, and a clear way to decide.

On this page

They run on the same engine

Your products, prices, and subscription groups live in App Store Connect, and the purchase itself goes through StoreKit. That is true whether you call StoreKit 2 yourself or let RevenueCat call it for you. RevenueCat is a layer on top of the same system, not a replacement for it.

That single fact removes the scariest part of the decision: lock-in. If you start on RevenueCat and later want to drop the dependency, you migrate the client code while your App Store Connect setup stays exactly where it is. The reverse is true too. So the choice is not a one-way door. It is a normal build-versus-buy call about the layer around the purchase, and you can revisit it later without re-doing your subscriptions.

What StoreKit 2 gives you

StoreKit 2, available since iOS 15, replaced the old delegate-and-notification model with a modern async/await API. It is free, ships with the platform, has no third-party dependency, and Apple maintains it. For an iOS-only app with straightforward purchase logic, it can be all you need.

Loading products and starting a purchase is direct:

import StoreKit
 
// Load the products you configured in App Store Connect.
let products = try await Product.products(
    for: ["com.yourapp.pro.monthly", "com.yourapp.pro.yearly"]
)
 
// Start a purchase.
let result = try await product.purchase()
switch result {
case .success(let verification):
    let transaction = try checkVerified(verification)
    await transaction.finish()
case .userCancelled, .pending:
    break
@unknown default:
    break
}

Checking whether the user is currently entitled reads straight off the device:

// Is the user entitled to anything right now?
var isSubscribed = false
for await result in Transaction.currentEntitlements {
    guard case .verified(let transaction) = result else { continue }
    if transaction.revocationDate == nil,
       transaction.productType == .autoRenewable {
        isSubscribed = true
    }
}

And you keep a listener running so renewals, refunds, and Ask to Buy approvals that happen outside your purchase flow still update state:

// Catch transactions that arrive outside the purchase call.
for await update in Transaction.updates {
    guard case .verified(let transaction) = update else { continue }
    // Refresh your entitlement state here.
    await transaction.finish()
}

The verification helper is the same one Apple's sample code uses, where StoreError is your own error type:

func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
    switch result {
    case .unverified:
        throw StoreError.failedVerification
    case .verified(let safe):
        return safe
    }
}

What StoreKit 2 does not hand you matters as much as what it does. Transaction.currentEntitlements is an on-device, signed source of truth, which is reliable, but if you want a cross-device record, server-side validation, or fraud signals, you build and host that backend yourself. There is no subscriber analytics dashboard, so churn, trial conversion, and revenue are yours to instrument. Beyond SubscriptionStoreView, paywall design and remote pricing changes are on you. And none of it covers Android.

Practical rule: with raw StoreKit 2 the purchase is easy and the bookkeeping around it is the project. If your app is iOS-only and the purchase logic is simple, that bookkeeping is small. If you want analytics, a server source of truth, or a second platform, it grows.

What RevenueCat adds on top

RevenueCat is the hosted layer that StoreKit 2 leaves to you: server-side receipt validation, an entitlements abstraction, a subscriber and revenue analytics dashboard, webhooks, paywall and experiment tooling, and one SDK that behaves the same across iOS, Android, and web.

The client code is short because the work moved to the dashboard and the server:

import RevenueCat
 
// Configure once, at launch.
Purchases.configure(withAPIKey: "appl_yourPublicKey")
 
// Fetch the offering you set up in the RevenueCat dashboard.
let offerings = try await Purchases.shared.offerings()
guard let package = offerings.current?.availablePackages.first else { return }
 
// Purchase, then read the entitlement straight off the result.
let result = try await Purchases.shared.purchase(package: package)
let isPro = result.customerInfo.entitlements["pro"]?.isActive == true

Checking entitlement anywhere else in the app is one call:

let customerInfo = try await Purchases.shared.customerInfo()
let isPro = customerInfo.entitlements["pro"]?.isActive == true

The difference is less about lines of code and more about what you never write: the validation server, the renewal bookkeeping, the analytics pipeline, and the second implementation for Android. Because offerings and entitlements are configured in the dashboard, you can also change packaging and pricing presentation without shipping an app update.

The real cost comparison

StoreKit 2 is free to use, but it is not free to run. You pay in engineering time, and if you want a reliable server-side source of truth, in a backend you build and host.

RevenueCat is free up to $2,500 in monthly tracked revenue (MTR), then charges on the order of 1% of tracked revenue on its Starter plan. Those numbers are current at the time of writing; confirm them on the RevenueCat pricing page before you plan around them. Two things are easy to misread:

  • MTR is gross revenue, measured before Apple takes its commission, not your net proceeds.
  • The fee scales with success. At $10,000 MTR you are looking at roughly $100 a month, which is small next to the revenue and the time saved. At much larger scale, the math is worth revisiting, and the fact that you can migrate to raw StoreKit 2 later keeps that option open.

The honest framing: at low revenue RevenueCat is free, so the question is time versus dependency, not money. The money question only shows up once the app is doing well, and by then you have data to make it with.

What iOS 27 changed

WWDC26 reworked App Store subscriptions, and some of it lands directly in StoreKit 2. The headline for developers is commitment plans: a monthly subscription with a 12-month commitment, which lets a customer pay for an annual plan in twelve monthly installments while still committing to the year.

In code, the new plan is a purchase option, and the commitment shows up on the transaction:

// iOS 27: offer the annual plan billed monthly.
try await product.purchase(options: [.billingPlanType(.monthly)])
 
// Inspect what the customer committed to.
if let commitment = transaction.commitmentInfo {
    // commitment.price is the full 12-month cost, alongside
    // progress and expiration for the active commitment.
}

The supporting API is worth knowing: every auto-renewable subscription now reports a billingPlanType, where .upFront is the classic pay-now annual plan and .monthly is the new installment plan, and pricingTerms lists the available plans so a SubscriptionStoreView can present them. Offer code redemption also changed, so offerCodeRedemption now returns a verificationResult when redemption completes and accepts a set of RedeemOption values. Group subscriptions, where one subscriber buys multiple seats, and cross-developer Bundles and Suites are arriving across late 2026.

Here is the part that matters for this comparison. With raw StoreKit 2 you adopt each of these APIs yourself as you decide to use them. With RevenueCat you get them through the same offering and entitlement model you already use, as support rolls out, without touching the purchase plumbing. For the business side of these changes, see App Store Subscription Pricing at WWDC26, and for the wider toolchain, the Xcode 27 guide.

How to choose

Reach for StoreKit 2 directly when:

  • Your app is iOS-only and the purchase logic is simple, for example one or two products and a single entitlement.
  • You have a real reason to avoid third-party SDKs, such as compliance rules, strict privacy requirements, or a preference for zero dependencies.
  • You are comfortable building whatever server-side validation you need, or you do not need one.

Reach for RevenueCat when:

  • You want subscription analytics, trial conversion, and churn without building the pipeline.
  • You plan to ship Android or web, now or later, and want one entitlement model across them.
  • You want to change paywalls and packaging without an app update.
  • You would rather ship in an afternoon than own the stack, and the roughly 1% past $2,500 MTR is a fair trade for that.

Most indie teams shipping their first paid app land on RevenueCat for the analytics and the time saved, and a few move to raw StoreKit 2 later if the fee or the dependency starts to matter. Because both sit on the same purchase system, that move is a refactor, not a rebuild.

Side by side

What you needStoreKit 2RevenueCat
Purchase engineStoreKit 2StoreKit 2, under the hood
DependencyNone, nativeOne SDK
Ongoing feeNoneFree under $2,500 MTR, then ~1%
Server-side validationBuild and host itIncluded
Cross-device entitlementsRoll your own source of truthIncluded
Android and webNot coveredOne SDK across platforms
Subscription analyticsInstrument it yourselfDashboard included
Change paywall or pricingShip an update or build remote configConfigure in the dashboard
iOS 27 commitment plansAdopt the StoreKit APIs yourselfThrough the same offering model
Best foriOS-only, simple, zero-dependencySpeed, analytics, cross-platform

FAQ

Do RevenueCat and StoreKit 2 use the same purchase system?

Yes. RevenueCat sits on top of StoreKit, the same system Apple exposes directly. Your products, prices, and subscription groups live in App Store Connect either way, so you are not locked in to either choice.

Is RevenueCat free?

It is free up to $2,500 in monthly tracked revenue, then charges on the order of 1% of tracked revenue, measured on gross revenue before Apple's commission, at the time of writing. Check their pricing page for current numbers, since pricing changes.

Can I migrate from RevenueCat to StoreKit 2 later?

Yes. Because your App Store Connect products and pricing do not change, moving to raw StoreKit 2 is a client-side refactor rather than a re-setup of your subscriptions.

Do I need a server for StoreKit 2?

For a single device, no, because Transaction.currentEntitlements works on-device. For a reliable cross-device source of truth, server-side validation, or fraud checks, you will want a backend, which is exactly the piece RevenueCat provides for you.

Does StoreKit 2 support the new iOS 27 commitment plans?

Yes. The new billingPlanType with .upFront and .monthly, plus the commitmentInfo on transactions, are StoreKit 2 APIs. RevenueCat exposes the same plans through its offering model as support rolls out.

Which is better for a first paid app?

For most indie teams, RevenueCat, because the analytics and the time saved outweigh the fee while revenue is low. Choose raw StoreKit 2 if you are iOS-only, your purchase logic is simple, and you want no third-party dependency.


Spaceport generates a production-ready SwiftUI Xcode project with the boring-but-essential parts of a paid iOS app already wired up, RevenueCat subscriptions included: offerings, entitlement checks, a paywall, onboarding, sign-in, and App Store Connect pricing across 25 markets. If you read this and land on RevenueCat, that is the path Spaceport scaffolds for you, so you start from working subscription code instead of an empty project. From an indie iOS dev, for indie iOS devs.

Read more at spaceport.build

Community appsJoin Discord