Use this page with AI

Copy this into your coding assistant and add your request.

Read https://openiap.dev/docs/features/subscription/upgrade-downgrade and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.

My request: [describe what customers should be able to do]
See an example request →

Subscription Upgrade & Downgrade

Understanding how each platform handles subscription tier changes is crucial for correctly detecting and displaying upgrade/downgrade states in your app. Both iOS and Android support subscription changes, but they handle them differently.

Overview#

When users change their subscription tier (e.g., from monthly to yearly, or from basic to premium), both platforms support upgrades and downgrades:

  • Upgrades: Moving to a higher-tier or longer-duration subscription
  • Downgrades: Moving to a lower-tier or shorter-duration subscription

The key difference is in how and when these changes take effect. Select your platform below to see specific implementation details:

Key Fields to Understand#

Upgrade Behavior (Charged Immediately)#

When a user upgrades to a higher-tier subscription (e.g., monthly → yearly, basic → premium):

  1. User is charged immediately for the new subscription tier
  2. A new transaction is created (though Transaction.updates may initially show the old product - this is a known StoreKit issue)
  3. autoRenewPreference immediately reflects the new product
  4. transaction.productID updates within a few minutes

Use pendingUpgradeProductId to detect when an upgrade is in progress, especially during the brief period when productId hasn't updated yet.

Downgrade Behavior (Applied at Next Renewal)#

When a user downgrades to a lower-tier subscription (e.g., yearly → monthly, premium → basic):

  1. No new transaction is created
  2. Change is reflected in the renewalInfo object only
  3. autoRenewPreference indicates the new (downgraded) product (Stack Overflow - autoRenewalPreference usage)
  4. transaction.productID remains unchanged until the renewal date
  5. User retains access to current tier until expiration

Check autoRenewPreference against productId to detect scheduled downgrades and inform users when the change will take effect.

Using pendingUpgradeProductId#

The pendingUpgradeProductId field is specifically designed to detect subscription tier changes. It is automatically calculated by comparing productID and autoRenewPreference.

How it works

The field is automatically calculated by comparing autoRenewPreference and productId:

Usage in your app

Simply check if pendingUpgradeProductId exists to detect tier changes in progress:

Best Practices#

  1. Always check pendingUpgradeProductId when displaying subscription status
  2. Show upgrade-in-progress UI when pendingUpgradeProductId is present
  3. For downgrades, inform users when the change will take effect (at renewal)
  4. Listen to purchase events to update UI when productId finally updates
  5. Test both scenarios in sandbox environment to understand the timing

Here's a complete React component that demonstrates all best practices for handling subscription tier changes:

Official References#