iOS Auto-Renewable Subscription: ~70% of US free-trial conversions fail to charge and enter Billing Grace Period (DID_FAIL_TO_RENEW / GRACE_PERIOD)
Hi everyone, I’m an iOS developer and I’m seeing an unusually high billing failure rate at the free-trial → paid conversion point. I’d appreciate any guidance on whether this looks like expected App Store billing behavior, a configuration issue, or a common implementation pitfall.
What I’m seeing
My app offers an auto-renewable monthly subscription with a 3-day free trial. Around the moment the trial ends and the first paid renewal should occur:
- ~70% of users hit billing failure and enter Billing Grace Period
- Before I enabled Billing Grace Period, a similar percentage appeared to go from trial directly to Expired
- Users are US storefront (USA / storefrontId 143441). The app is not released in China.
App Store Connect configuration (summary)
- Product type: Auto-Renewable Subscription
- Duration: 1 month
- Product ID: monthly_trial
- US price: $12.99 / month
- Free trial: 3 days (P3D)
- Environment: Production
- Family Sharing: Off (if relevant)
Tech / integration
- iOS client is currently StoreKit 1 (uses SKReceiptRefreshRequest)
- I have a backend and I’m using App Store Server Notifications V2 to update subscription status
- During Grace Period, I currently continue to grant entitlement and prompt users to update their Apple ID payment method
Redacted Server Notifications V2 example
Below is a typical sequence (IDs masked, only key fields shown). Timestamps are epoch milliseconds; my logs may show local time.
Event A — trial start
- notificationType: SUBSCRIBED
- subtype: INITIAL_BUY
- offer: FREE_TRIAL (P3D)
- price: 0
- storefront: USA (143441)
- productId: monthly_trial
- originalTransactionId: 2000029926****436
- purchaseDate (ms): 1768156450000
- expiresDate (trial end, ms): 1768415650000
Event B — trial ends, first paid renewal attempt fails, grace period begins
- notificationType: DID_FAIL_TO_RENEW
- subtype: GRACE_PERIOD
- expirationIntent: 2 (billing error)
- isInBillingRetryPeriod: true
- renewalPrice: 12990 (USD equivalent to $12.99)
- renewalDate (ms): 1768415650000
- gracePeriodExpiresDate (ms): 1769798050000
- transaction expiresDate (ms): 1769798050000
- appTransactionId: 7051882678****984
- originalTransactionId: 2000029926****436
Questions
- Has anyone seen very high DID_FAIL_TO_RENEW / GRACE_PERIOD rates for US trial conversions? Is this ever normal (e.g., payment verification patterns), or does it usually indicate a problem?
- Are there known pitfalls with StoreKit 1 + receipt validation + Server Notifications V2 that could make this look worse than it is (e.g., entitlement misclassification, timing issues, relying on stale receipt data, etc.)?
- What’s the recommended user-facing flow during Billing Retry / Grace Period? (We currently grant access and ask users to update payment method.)
- Would migrating the client to StoreKit 2 improve reliability of detecting in-grace/in-retry states (even if it doesn’t affect billing success itself), or is the backend approach sufficient?
What I’ve checked
- App Store Connect pricing and trial configuration appear correct
- We do not revoke access during Grace Period
- The rate remains unusually high (~70%)
Thanks in advance for any similar cases, diagnostic tips, or best practices. I can provide additional anonymized samples if helpful.