TL;DR: During a subscription grace period the customer still has access, so the only message that belongs is a service notice: what failed, how to fix payment, and the real deadline. Suppress upsell sends until the store's recovery event confirms payment.
A renewal payment fails, the customer keeps their access, and your campaign calendar keeps rolling. That gap between "payment broken" and "subscription over" is the subscription grace period, and it is where lifecycle messaging does the most quiet damage. Send a winback offer to someone who was never lost, or a discount to someone whose card just needs updating, and you have turned a recoverable billing event into a strange customer experience.
This guide is for lifecycle, product, and subscription operations leads at mobile and consumer subscription businesses. It covers handling subscription grace periods in lifecycle messaging only: what the customer should hear while payment recovery runs but access stays active. The recovery machinery itself — retry timing, card-update flows, and the support handoff — is a separate build, covered in failed payment recovery. Teams usually justify this kind of lifecycle automation with business process automation ROI; a grace-period message spec earns it by preventing involuntary churn you would otherwise manufacture yourself.
When a failed renewal is not a churned customer
The short answer: treat the grace window as an open support ticket, not a marketing moment. The customer paid until now, the store is retrying their card, and they still have what they paid for. Everything they hear from you should match that state.
Three facts set the stakes:
- Grace periods are opt-in but broadly available. Apple offers Billing Grace Period per app at 3, 16, or 28 days; Google Play enables a grace period by default on all auto-renewing base plans; Stripe and Paddle support configurable retry windows; Amazon does not support one, per the RevenueCat grace period reference.
- Access during grace is the point of the feature. Google Play's lifecycle doc states the user should still have access to their subscription entitlement during the grace period, and Apple's StoreKit documentation says to provide full service throughout it.
- Recovery inside the window is quiet. When a Play subscription recovers during grace, the renewal date does not reset. If Apple collects within the grace period, there is no interruption to the subscriber's days of paid service or to your revenue, per Apple's subscription overview.
So the best possible outcome — card fixed, subscription continues, customer barely notices — is also the outcome your messaging can ruin by treating the person as already gone.
Map entitlement and billing states before writing a single message
You cannot write one grace-period email, because "grace period" is not one state. Each store reports the window differently, and the same word means different access on different platforms. Build the map first; the messages hang off it.
| Platform | What enters the state | Access during the window | What ends it |
|---|---|---|---|
| Google Play grace period | SUBSCRIPTION_IN_GRACE_PERIOD RTDN; subscriptionState = SUBSCRIPTION_STATE_IN_GRACE_PERIOD |
Retained; Play extends expiryTime while grace runs |
Recovered renewal (date does not reset) or SUBSCRIPTION_ON_HOLD — account hold, access revoked |
| Google Play account hold | SUBSCRIPTION_ON_HOLD RTDN after grace expires |
Revoked; block access per Play's lifecycle doc | User fixes payment and Play recovers, or hold ends — default hold length is 60 days minus your grace period |
| App Store subscription grace period | DID_FAIL_TO_RENEW notification; isInBillingRetry true plus gracePeriodExpiresDate set |
Retained until gracePeriodExpiresDate — 3, 16, or 28 days per app, capped at 6 days on weekly plans |
Recovered renewal inside the window, or expiration after it; Apple retries up to 60 days total |
| Apple billing retry, no grace configured | DID_FAIL_TO_RENEW; isInBillingRetry true, no gracePeriodExpiresDate |
Your policy — Apple says paid-service days pause until collection | Recovery within the 60-day retry window |
| RevenueCat (any store) | BILLING_ISSUE with grace_period_expiration_at_ms set, plus CANCELLATION with cancel_reason = BILLING_ERROR |
Retained while the store-reported grace period stands | RENEWAL if the charge succeeds, EXPIRATION if the grace period ends unrecovered |
| Stripe | invoice.payment_failed; subscription past_due |
Your policy — Stripe advises reviewing retry schedule, final action, and access policy together | A successful retry or your chosen final action; Smart Retries default is up to 8 retries in 2 weeks on new accounts |
A Stripe subscription grace period is not a store feature with a fixed window — it is whatever access policy you pair with your retry schedule, which is why Stripe tells you to review the two together. The App Store billing grace period, by contrast, is a named App Store Connect setting with fixed durations; your messaging can quote its exact end date because the store reports it.
Three mapping rules catch the cases teams get wrong:
Grace entry is not graceful in the events. RevenueCat fires BILLING_ISSUE and a CANCELLATION (BILLING_ERROR) the moment a charge fails, and notes that with grace enabled the subscription is "past due but not expired" until the window ends. If your lifecycle tool reads CANCELLATION as "canceled by user," it will send a sorry-to-see-you-go email to a customer mid-grace. Key off the grace fields — grace_period_expiration_at_ms on BILLING_ISSUE, or grace_period_expires_date on the subscriber endpoint — not off the cancellation label, per the RevenueCat event field reference.
There is an empty pocket before the store reports grace. A configured grace period does not hold entitlements open the instant a billing period ends. RevenueCat reflects the store's last known expiration until the store reports grace or pushes the period end forward, so on Google Play entitlements can sit empty for minutes or hours in between — the renewal-extensions doc walks through this edge. A "your access ended" email triggered on an empty entitlement check fires into that gap and is wrong within the hour.
Grace and hold share a signal but not a meaning. In RevenueCat's customer model, billingIssueDetectedAt is non-null from the SUBSCRIPTION_IN_GRACE_PERIOD RTDN until the issue resolves — it covers both grace (access retained, isActive true) and account hold (access revoked, isActive false). Detect the billing issue with one flag; decide access with the other.
If your lifecycle stages live in a CRM, this map is also where lifecycle stage sync regressions start: a "past due" stage that overwrites "active" on the wrong event is a messaging bug shipped to every channel.
Separate the service notice from the upsell
Subscription grace period messaging is a service-notice problem before it is a copywriting problem. Once a customer is inside the grace window, exactly one message type is allowed: the service notice. That is a transactional message whose only job is to fix the payment — what failed, what happens next, and the real deadline. Everything else — upsell, cross-sell, annual-plan offers, winback — waits for the recovery signal.
Write the service notice against the state map, not against your email cadence:
- Say what happened plainly. "Your March renewal payment did not go through" — no decline codes, no internal failure reasons, no guilt.
- Give the actual deadline, not a vague "soon." The store hands you the date:
gracePeriodExpiresDateon Apple,grace_period_expiration_at_mson RevenueCatBILLING_ISSUE, the extendedexpiryTimeon Play. Put that date in the message. - Keep access status honest. During grace the customer still has access; say so. Threatening a cutoff while the product still works reads as a bluff, and stating the wrong end date reads as a bug.
- Send them to the store's fix path. On mobile, the customer updates payment inside their Apple or Google account; link to your in-app prompt or account page that routes them there, per Play's guidance to encourage users to fix their payment method.
Then dedupe the senders. Google Play already informs users in a grace period that their payment was declined, and Stripe's failed-payment email setting sends a notice after each failed payment. One sender per message type: if the store or processor owns the payment-declined notice, your lifecycle tool owns the account-level service notice — and nothing else. A subscription business running both plus a dunning sequence is triple-mailing the same event.
The suppression half matters as much as the send. At BILLING_ISSUE / grace entry, remove the customer from promotional audiences across email, push, and ads until the recovery signal — the same discipline as keeping a preference center in sync across systems. A customer whose card failed Tuesday should not get the "upgrade to annual" campaign on Wednesday. This is also the honest answer to whether marketing should keep sending during a dunning grace period: service notices yes, campaigns no.
Confirm recovery before resuming campaigns
Recovery is a store event, not a hope. Resume campaigns and audiences only when the recovery signal lands — and read the event stream carefully, because it lies about order.
The signals that mean "recovered":
- RevenueCat:
RENEWAL. If billing succeeds at any point during grace,RENEWALfires and entitlements were never revoked. - Google Play: a successful renewal after
SUBSCRIPTION_IN_GRACE_PERIOD, with the original renewal date kept. - Apple: the subscription renews inside the grace window — no interruption to paid-service days, and
gracePeriodExpiresDateclears. - Stripe: the invoice pays;
past_dueresolves.
The signals that mean "window closed": EXPIRATION (with expiration_reason = BILLING_ERROR on RevenueCat) or SUBSCRIPTION_ON_HOLD — access is now legitimately gone, and only now does winback eligibility start.
Two failure modes to engineer around:
Events arrive out of order. RevenueCat is explicit that BILLING_ISSUE, CANCELLATION, and EXPIRATION are dispatched at the same time and can arrive in a different order than described, and that a RENEWAL may even appear before the billing issue in the customer-history timeline — check the timestamps, not the delivery order. A lifecycle flow that unsuppresses on CANCELLATION seen before BILLING_ISSUE puts the customer back into campaigns mid-failure.
"Still retrying" is not "recovered." A new expiryTime pushed forward, a SUBSCRIPTION_EXTENDED on Play, or a passed retry attempt is the store still working. On Google Play, Google can defer a renewal charge by less than 24 hours and then send RENEWAL or BILLING_ISSUE within that window. Wait for the money event, then restore the customer's campaign eligibility in the same transaction that flips their state back — otherwise the winback flow and the recovery flow fire at the same person in the same week.
Grace-period messaging matrix
This is the working asset: one table your ops lead can paste into the messaging spec. It turns every store's event vocabulary into a send/no-send decision. The example rows use a synthetic monthly subscription — a documented state model, not a measured customer result.
| Customer state (store signal) | Access now | Allowed message | Suppress from campaigns | Exit / recovery signal |
|---|---|---|---|---|
Grace period, Play (SUBSCRIPTION_IN_GRACE_PERIOD) |
Yes | Service notice: payment failed, fix path, grace end date | Yes | RENEWAL (original date kept) or SUBSCRIPTION_ON_HOLD |
Account hold, Play (SUBSCRIPTION_ON_HOLD) |
No | Service notice: access paused, how to restore | Yes | RENEWAL on recovery; hold ends default 60 days minus grace |
Grace period, Apple (isInBillingRetry + gracePeriodExpiresDate) |
Yes | Service notice with that expiry date | Yes | Renewal inside window, or expiration after it |
Billing retry, Apple, no grace (isInBillingRetry only) |
Your policy | Service notice; state the access decision you chose | Yes | Recovery inside 60-day retry window |
BILLING_ISSUE with grace_period_expiration_at_ms (RevenueCat) |
Yes | Service notice keyed to that timestamp | Yes | RENEWAL or EXPIRATION (BILLING_ERROR) |
past_due (Stripe) |
Your policy | Service notice; keep it to one sender if Stripe's own failed-payment email is on | Yes | Invoice paid, or your configured final action |
Recovered (RENEWAL, paid invoice) |
Yes | Optional short "you're all set" receipt-style note | No — restore in the same state flip | — |
Expired (EXPIRATION, BILLING_ERROR) |
No | Winback eligibility starts here, never earlier | N/A | Resubscribe |
Worked example, labeled synthetic: a monthly Apple subscription fails to renew on March 1. DID_FAIL_TO_RENEW fires, isInBillingRetry is true, and gracePeriodExpiresDate reads March 17 on the app's configured 16-day grace. The matrix says: service notice on day 1 (what failed, fix path, March 17 deadline) and one reminder on day 10; the customer drops out of the upgrade campaign running March 5–20 at the moment BILLING_ISSUE lands. On March 9 the customer updates their card and Apple collects: RENEWAL fires, the customer re-enters campaign audiences in the same state flip, and their days of paid service were never interrupted. Total messaging during the window: two service notices, zero promotions.
To use the matrix, fill three inputs from your own stack — which store events reach your messaging tool, which flag carries the access decision (isActive vs billingIssueDetectedAt on RevenueCat is the cleanest split), and which system owns suppression. If suppression lives in a different tool than sends, an audience sync gap will leak promos to in-grace customers even when the matrix is right.
FAQ
What does a subscription in grace period mean?
It means the latest renewal payment failed, the store is still retrying, and the subscription is past due but not expired — the customer keeps their access until the grace window ends. On Google Play the resource reports SUBSCRIPTION_STATE_IN_GRACE_PERIOD; on Apple, isInBillingRetry is true with a gracePeriodExpiresDate present.
How long is the Apple subscription grace period?
You choose 3, 16, or 28 days per app in App Store Connect, and it applies to all auto-renewable subscriptions in that app. Weekly subscriptions are capped at a 6-day actual grace period regardless of the chosen length. Apple's Billing Grace Period is optional and configurable per the App Store Connect help.
What happens after the grace period ends?
If payment recovered inside the window, the subscription simply continues — on Play the renewal date does not reset. If it did not, the subscription moves to account hold (Play, access revoked but recoverable; default hold length is 60 days minus the grace period) or to expiration (EXPIRATION on RevenueCat, BILLING_ERROR reason), and the customer loses access. Only at that point should winback messaging begin.
How does a grace period work alongside dunning?
Grace period is the access window; the dunning grace period work — retries and payment-fix prompts — is what happens inside it. The store owns payment retries; you own the service notice and the suppression. Both end on the same event: RENEWAL for recovered, EXPIRATION or hold for lost.
Should customers keep access during a subscription grace period?
Yes — that is what the feature is for. Both Google Play and Apple document retained access through the grace window; cutting access at first decline punishes a customer whose payment may recover in days and turns a soft decline into a support ticket and a real cancellation. Set your access policy to match the store-reported state, not the failed charge.
Answer clarity notes
- Dates: the article's publish date is August 19, 2025. All linked vendor documentation is living documentation checked on November 9, 2026 — store field names, default retry behavior, and grace-period options can change; verify against current docs before building.
- Scope: this is messaging guidance for lifecycle, product, and subscription operations at mobile and consumer subscription businesses. It covers what the customer hears during the grace window, not retry scheduling, debt collection, or platform-policy compliance advice.
- Evidence: all platform behavior above is verified public documentation — Google Play lifecycle, Apple App Store Connect and StoreKit, RevenueCat event flows, and Stripe retry docs. Durations and defaults cited (Apple 3/16/28 days, Play's 60-days-minus-grace hold, Stripe's 8 retries in 2 weeks) are vendor-documented configurations, not benchmarks.
- Synthetic examples: the March Apple example and the matrix rows are a synthetic state model built on documented behavior — planning guidance, not guarantees and not a measured customer result.
- Do not infer: exact grace length, hold length, and retry count depend on your own store console and processor settings. The two-notice cadence in the example is a proposed starting point, not a tested standard.
Sources
- Google Play: subscription lifecycle
- Apple: enable Billing Grace Period for auto-renewable subscriptions
- Apple: auto-renewable subscriptions
- Apple StoreKit: gracePeriodExpirationDate
- RevenueCat: webhook event types and fields
- RevenueCat: common webhook flows
- RevenueCat: how grace periods work
- RevenueCat: Google Play renewal extensions and entitlements
- Stripe: automate payment retries
- Stripe: automate customer emails
That'sGonnaHelp can audit one subscription lifecycle flow — state map, service notices, and suppression rules — before the next failed-renewal season. Bring the events your stores actually send.