Compliant implementation of dynamic pricing tiers for upgrades and extensions via StoreKit

Hello everyone,

I am designing an in-app subscription and pass extension/upgrade system for an iOS app and want to ensure full compliance with App Store Review Guideline 3.1.1. Because pricing in our system depends on the user's historical purchase price rather than static store catalog prices, direct fixed-SKU purchases aren't sufficient on their own.

Business Logic Overview

  • Extensions: An extension costs 50% of the price the user originally paid for their plan.

    • Example: If a user bought Plan A at $200, their extension cost is $100 (even if Plan A currently retails at $150).
  • Upgrades: An upgrade charges the delta between the target plan's current price and the user's original purchase price.

    • Example: A user bought Plan A for $200, and Plan B currently costs $250. The upgrade cost is $\max(0, 250 - 200) = 50$.

Proposed Technical Solution

  1. User requests an extension or upgrade from the iOS client.
  2. The backend server calculates the exact delta amount based on user purchase history.
  3. The backend maps this calculated amount to a pre-defined Tiered StoreKit Product ID (e.g., com.app.tier_50).
  4. The iOS app receives the Product ID and executes the transaction via StoreKit 2 (Product.purchase()).
  5. The backend validates the transaction JWS signature with Apple and updates the user's access duration.

Questions for the Community & Apple Engineers

  1. Has anyone implemented backend-resolved dynamic Tiered SKUs for top-ups or price deltas? Did this pass App Review without issues under Guideline 3.1.1?
  2. Are there recommended patterns when configuring price-point tier SKUs (Consumable vs Non-Renewing Subscription) in App Store Connect for variable delta payments?
  3. For auto-renewing subscriptions, is it preferred to handle extensions strictly via StoreKit 2 Promotional Offers rather than delta SKUs?

Any feedback or real-world experience with similar pricing structures would be greatly appreciated!

You are computing the delta in one currency, but each SKU carries a different price in every storefront, picked from that currency's own price-point ladder.

I suggest to record what the user actually paid from the signed transaction itself.

Also good to decide a rounding rule up front. The gaps between Apple price points are not uniform and get wider as prices go up, so many deltas will not have an exact SKU. Rounding down to the nearest SKU means you never overcharge, at the cost of a small loss on some upgrades.

Regarding consumable vs non-renewing: a consumable models "pay a one-off amount", a non-renewing subscription models "buy a fixed period of access". Since your extension buys time, non-renewing may describe it more honestly, but I have seen both used.

In any case, I highly recommend to localize your prices. The store only does currency conversion, localization is instead price adjustment based on affordability per each country. Try free tools like https://pricepush.app/price-localizer to have an idea of how much to charge.