We kept running into mismatch issues: a user bought on the web but the app showed a lapsed status, or vice versa. We implemented a sync where the web checkout writes a subscription record and a gateway receipt, then pushes the status to our subscription service which both the app and server read.
We used server-side hooks to update RevenueCat/Adapty and also kept a local mapping of web order id → in-app entitlement id. That made refunds and targeted win-back offers much simpler. When we issued a refund on web, the app immediately reflected the change and we could trigger a targeted email with a special rejoin offer.
The biggest ops win was fewer manual reconciliations and faster customer support responses.
What patterns do others use to avoid status drift between web and app subscriptions?
We pushed every successful web purchase to RevenueCat via server API.
That kept app entitlements in sync instantly.
Also reconcile nightly to catch edge cases.
Syncing was a game changer for recovery.
When a refund or failed payment occurred we updated RevenueCat and sent a tailored win-back offer within hours.
That reduced churn from billing errors.
We wrote web order ids back to the user profile and used that to find matching in-app receipts.
Made refunds and support tickets much faster to resolve.
Push web events to revenuecat
No more drift
The reliable pattern is server-first truth: accept payments on the web, write a canonical subscription record on your server, and then propagate that state to whichever downstream system (RevenueCat/Adapty) you use. This avoids race conditions and gives you a single place to trigger win-back logic and refunds.
We added an audit log for every sync call between web and the app.
When something failed we retried and alerted the ops channel.
Nightly reconciliation caught odd mismatches for us.
Simple and effective.