RevenueCat vs Superwall for iOS apps
What RevenueCat does
RevenueCat sits on top of StoreKit and owns subscription state. You define products and entitlements in its dashboard, and your app asks a simple question: does this user have access? It validates receipts server-side, handles restores across devices, supports cross-platform entitlements if you also ship on Android or web, and reports revenue. It includes a paywall builder, but its center of gravity is reliable, correct entitlement state. The iOS SDK uses a public key that starts with appl_, which is safe to ship.
What Superwall does
Superwall owns the paywall presentation layer. You build paywalls in its dashboard, assign them to named placements like onboarding_complete, and run A/B tests on layout, copy, and price. Because paywalls are fetched at runtime, you iterate on the highest-leverage conversion surface without shipping an App Store update. Superwall does not aim to be your source of truth for entitlements. Instead it integrates with RevenueCat to delegate purchases and read access state, while it focuses on which paywall to show and measuring what converts.
Using them together
The common production setup is Superwall in front and RevenueCat behind. Superwall decides when and which paywall appears and runs the experiment; the purchase is delegated to RevenueCat, which records the entitlement and keeps it correct everywhere. Your feature gates then check RevenueCat. This pairing gives you fast paywall iteration and a trustworthy entitlement system at the same time. Both keys are public client keys, so neither requires a secret in the app.
A SwiftUI example
A minimal sketch of the two roles, Superwall presenting and RevenueCat gating:
import RevenueCat
import SuperwallKit
import SwiftUI
@main
struct MyApp: App {
init() {
Purchases.configure(withAPIKey: "appl_YourPublicKey")
Superwall.configure(apiKey: "pk_YourPublicKey")
}
var body: some Scene {
WindowGroup { ContentView() }
}
}
struct ContentView: View {
var body: some View {
Button("Unlock Pro") {
// Superwall decides whether to show a paywall.
Superwall.shared.register(placement: "unlock_pro")
}
.task {
// RevenueCat is the source of truth for access.
let info = try? await Purchases.shared.customerInfo()
let hasPro = info?.entitlements["pro"]?.isActive == true
print("Pro active: \(hasPro)")
}
}
}
Alternatives
StoreKit 2 alone can power a simple single-product app with no third-party dependency, and Apple's own paywall and subscription tools have improved, so a minimal app may not need either. If you want only entitlement correctness, RevenueCat by itself is enough. If you mostly want paywall experimentation and already have entitlements handled, Superwall by itself works. The combined setup is for teams that want both reliability and rapid paywall testing.
FAQ
Do I have to pick one of RevenueCat or Superwall?
No. They are complementary. RevenueCat handles entitlements and receipt validation, Superwall handles paywall design and A/B testing. Superwall has a built-in integration that delegates purchases to RevenueCat, so many teams run both.
Which one do I need if I just want a paywall?
If you mainly need to ask whether a user has Pro and keep that state correct, RevenueCat alone is enough and it includes a basic paywall builder. If you want to experiment heavily on paywall design and pricing without app updates, add Superwall.
Do both ship a public key in the app?
Yes. RevenueCat uses a public app-specific key that starts with appl_, and Superwall uses a public API key. Both are safe to ship in the binary. Neither requires a secret key in the app. AppFlight stores both as client keys.