I wanted one source of truth for revenue after moving checkout to the web, so I synced everything to the same customer in RevenueCat:
- On first web session I create a user_id. If the user pays on the web, I send Stripe events to my backend, then to RevenueCat’s API using that same user_id. Entitlements reflect the web product.
- The app configures RevenueCat with the same user_id on login. If the user later buys in-app, RevenueCat merges entitlements, and I block duplicate subscriptions by hiding the paywall for active web subs.
- Renewals and refunds from the web arrive via Stripe webhooks and I forward them to RevenueCat so the entitlement stays accurate. I also export RevenueCat events and my web events to a warehouse for reconciliation.
- If users switch from Apple to web, I transfer the customer to my stable user_id after explicit confirmation to avoid hijacking.
So far, MRR in RevenueCat matches Stripe within 1 to 2 percent and entitlements stay in sync across platforms.
What edge cases am I missing here, especially around upgrades, proration, or restoring purchases on a fresh device?