# Cross-platform entitlement sync if app is on both stores

- **Pattern:** `ab-000410` (`app-store-iap-subscriptions.restore-entitlements.cross-platform-sync`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000410
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000410)

## Why it matters

A user who subscribes on iOS, reinstalls on Android, and discovers their subscription is not recognized will either double-pay or churn. Validating Apple receipts into one database table and Google purchase tokens into another with no shared `user_id` link splits a single paying customer into two half-customers — and the data-integrity hit compounds when refunds, cancellations, or plan changes arrive on one platform but never reach the other. Cross-platform sync is a churn and support-load problem, not a store policy one.

## Severity rationale

Low because it only affects users who actively switch platforms, though impact per affected user is high.

## Remediation

Configure both iOS and Android apps under a single RevenueCat (or Adapty/Qonversion) project using the same entitlement identifiers — the SDK then resolves entitlements against a unified customer profile automatically. For a custom backend, have both `api/validate-apple.ts` and `api/validate-google.ts` write to a single `user_entitlements` table keyed by your internal `user_id`, not by the platform-native purchase identifier, so a logged-in user sees the same `is_premium = true` on either device.

## Detection

- **ID:** `cross-platform-sync`
- **Severity:** `low`
- **What to look for:** Count all relevant instances and enumerate each. If the app is distributed on BOTH iOS App Store and Google Play, determine how subscription entitlements are synchronized. A user who subscribes on iOS should ideally have their entitlement recognized if they switch to the Android version, and vice versa. Look for: (1) RevenueCat — handles this automatically if both iOS and Android are configured in the same RevenueCat project with the same entitlement IDs. (2) Adapty — same as RevenueCat if configured with cross-platform profiles. (3) Custom backend — look for an entitlement service that normalizes Apple and Google purchase records into a unified user-level premium flag stored in the database. The critical failure is a user subscribed on iOS who installs the Android app and finds their subscription not recognized. This is not a store rejection issue but a significant UX/churn risk.
- **Pass criteria:** App is single-platform (skip), or cross-platform entitlement sync is handled via RevenueCat/Adapty/Qonversion (automatic), or a custom backend unifies entitlements. At least 1 implementation must be verified.
- **Fail criteria:** App ships on both iOS and Android but iOS subscriptions are not recognized on Android and vice versa — entitlements are validated per-platform with no cross-reference to a unified user account.
- **Skip (N/A) when:** App is iOS-only or Android-only; or cross-platform entitlement approach cannot be determined from codebase.
- **Detail on fail:** `"iOS purchase validation in api/validate-apple.ts and Android validation in api/validate-google.ts write to separate database tables with no shared user_id link — iOS subscribers are not recognized on Android"`
- **Remediation:** Use RevenueCat or Adapty and configure both iOS and Android apps under the same project — cross-platform entitlement sync is automatic with linked user identity. For custom backends, ensure both validation paths write a `is_premium = true` flag to the same user record.


  Review the configuration in `src/` or `app/` directory for implementation patterns.

- **Cross-reference:** For related patterns and deeper analysis, see the corresponding checks in other AuditBuffet audits covering this domain.

---

Taxons: data-integrity

HTML version: https://auditbuffet.com/patterns/ab-000410
