Syncing web subscriptions to adapty: what actually broke and how i fixed it

We had a rough time when we started issuing subscriptions on the web but needed the app to honor entitlements instantly. We used Adapty/RevenueCat style integrations to sync status, but several issues cropped up.

Problems we hit:

  • timing gaps where the app opened before the server had processed the web payment
  • mismatched user ids across web and app
  • refresh failures when network lag caused the app to show stale entitlements

Fixes that mattered:

  • include the payment provider’s transaction id and the web user id in the payment metadata
  • when the app starts, call a server endpoint that returns the current entitlement state rather than relying only on client side cached state
  • implement a short polling or push-notification mechanism so the app updates entitlements immediately after web purchase
  • ensure the web flow writes to the same backend user id the app uses — hashed email or a persistent id helps

Did you build a simple reliable pattern for this sync that survived race conditions and offline app opens? How did you handle identity linking?

We wrote a small server endpoint that returns entitlements by user id and transaction id.

App calls it on startup and after a purchase event.

Also used push to notify the app when web payment completed.

Keeping the same hashed id across web and app fixed most mismatches.

I force the app to verify entitlements with our server after a web checkout. The server confirms the payment and flips the entitlement. We push a silent update so the app shows access immediately.

Doing this via a web platform that writes payment metadata into our backend made the flow reliable.

Make the app trust server state not local cache. After a web purchase hit an endpoint that returns entitlements. If possible send a push to the app to refresh immediately.

That solved most race problems for us.

App ask server entitlement on open then accept push updates

The reliable pattern is server authoritative entitlements. On web payment completion write the purchase and payment transaction id to the server and map it to the canonical user id. The app should never assume local state is current. On app start and after any purchase attempt call the server entitlement endpoint. Implement server side idempotency and a push or webhook that triggers the app to refresh. For identity linking prefer a stable unique id such as a hashed email or an account id created prior to purchase to avoid the orphaned records problem.

We added a purchase webhook that updates the user record and triggers an app push.

App refreshes entitlement immediately and shows correct access.

Mapping by hashed email avoided most edge cases.

Server truth and immediate app refresh fixed our sync issues.

Hash ids and push updates if possible.