FAILED PAYMENTSGOOGLE PLAY

How to reduce churn on Google Play: grace period and account hold

How Google Play grace period and account hold work, which real-time developer notifications to handle, in-app messages for declines, and how to win users back.

Published 6 min read

On Google Play, Google charges the customer, retries failed payments and shows the cancel button. You cannot retry a charge or touch the customer’s payment method. What you do control: how long the grace period and account hold last, whether the customer keeps access, what your app shows them, and how quickly you react when a subscription recovers or ends.

This guide covers the grace period, account hold, the real-time developer notifications (RTDN) and subscriptionsv2 states behind them, in-app messaging for payment declines, deep links to the subscription center, restore and resubscribe, and voided purchases. It sticks to Google’s documentation: subscription lifecycle, about subscriptions, the RTDN reference and Help Google dispute chargebacks (all accessed November 2026).

What Google does when a renewal fails

When a renewal payment fails, Google notifies the user and keeps trying to renew for some time before the subscription ends. Google’s docs call this the recovery period, made of a grace period followed by an account hold. During it, Google sends the user emails and notifications asking them to update their payment method.

Phase User’s access subscriptionState RTDN when it starts
Grace period Keeps access SUBSCRIPTION_STATE_IN_GRACE_PERIOD SUBSCRIPTION_IN_GRACE_PERIOD (6)
Account hold Loses access SUBSCRIPTION_STATE_ON_HOLD SUBSCRIPTION_ON_HOLD (5)
Recovered Access restored SUBSCRIPTION_STATE_ACTIVE SUBSCRIPTION_RECOVERED (1)
Not recovered Access ended SUBSCRIPTION_STATE_CANCELED, then EXPIRED SUBSCRIPTION_CANCELED (3), then SUBSCRIPTION_EXPIRED (13)

Grace period

Google’s lifecycle guide says:

  • Grace period is enabled by default on all auto-renewing base plans. You can change its length or turn it off in the Play Console, and Google warns that a shorter length may reduce the number of subscriptions recovered.
  • During the grace period the user should keep access. autoRenewEnabled stays true, and Google extends expiryTime until the grace period ends.
  • If the user fixes their payment method, the subscription renews with its original renewal date.
  • Changing the grace period length only affects renewals that enter the grace period after the change.
  • If you set 0 days, Google still waits at least 1 day (a “silent grace period”) to leave time for retries. The subscription stays active during those 24 hours and you will not receive a grace period RTDN.

If your app only uses queryPurchasesAsync() to check entitlement, grace periods are handled for you, because the Play Billing Library keeps returning those purchases as active.

Account hold

Account hold follows the grace period:

  • It is enabled by default, and its default length is 60 days minus the grace period. You can change it or turn it off in the Play Console, with the same warning about shorter lengths.
  • Before the subscription enters account hold, Google makes additional attempts to charge for up to 48 hours, while the user keeps access.
  • During account hold you should block access. expiryTime is in the past and queryPurchasesAsync() no longer returns the subscription.
  • If the user fixes their payment, you get SUBSCRIPTION_RECOVERED, the purchase token stays the same, and you must restore access. Unlike recovery during the grace period, the billing date moves to the date of recovery.
  • If the hold ends without a fix, you get SUBSCRIPTION_CANCELED and then SUBSCRIPTION_EXPIRED.
  • A paused subscription that resumes with a failing payment method goes straight into account hold.

Google also notes that users can cancel, restore or repurchase while on hold, so your backend must keep handling those events.

Real-time developer notifications

RTDNs are delivered through Cloud Pub/Sub and only carry the notification type and purchase token. Google’s guidance is to call purchases.subscriptionsv2.get from your backend on each notification to read the full state. The RTDN reference lists the subscription types; the ones that matter most for churn:

Code Type What to do
6 SUBSCRIPTION_IN_GRACE_PERIOD Keep access; ask the user to fix their payment
5 SUBSCRIPTION_ON_HOLD Remove access; tell the user why
1 SUBSCRIPTION_RECOVERED Restore access (also sent when a subscription resumes from pause)
2 SUBSCRIPTION_RENEWED Normal renewal
3 SUBSCRIPTION_CANCELED Voluntary or involuntary cancellation; check canceledStateContext
7 SUBSCRIPTION_RESTARTED User restored a cancelled, not yet expired subscription
12 SUBSCRIPTION_REVOKED Revoked before expiry, for example after a chargeback; remove access
13 SUBSCRIPTION_EXPIRED Remove access
4 SUBSCRIPTION_PURCHASED New purchase, including a resubscribe

On a cancellation, canceledStateContext tells you whether the user, the system or you cancelled, and for user cancellations userInitiatedCancellation can include the reason the user gave. Use it: a cancellation after account hold is a payment problem, not a decision to leave.

In-app messaging for payment declines

Google offers a ready-made message for payment problems. If you call BillingClient.showInAppMessages() with InAppMessageCategoryId.TRANSACTIONAL, Google Play shows a temporary snackbar telling the user their payment was declined, with a deep link to fix their payment method on Google Play. According to Google’s subscriptions guide, the message is shown once per day during the grace period and account hold, and Google recommends calling the API each time the user opens the app.

If the user fixes their payment, the call returns SUBSCRIPTION_STATUS_UPDATED with a purchase token. Refresh the subscription from your backend and restore access straight away.

For users who reach your content outside the app (on the web, for example), Google suggests a push notification or an email when access stops because of account hold.

Your app should link to subscription management from its settings screen. Google documents two URLs:

  1. All subscriptions: https://play.google.com/store/account/subscriptions
  2. One subscription (recommended): https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package

The second opens the management page for that subscription, where the user can manage their payment methods, cancel, resubscribe or pause. Use it in your own payment emails, too.

Restore, resubscribe and win-back

Google separates two actions, both shown to the user as a Resubscribe button in the Play Store:

  • Restore: before expiry, a cancelled subscription is restored and continues to renew as if it were never cancelled. It keeps the same purchase token and you receive SUBSCRIPTION_RESTARTED. Google says all apps must support restore.
  • Resubscribe: after expiry, if the base plan allows it, the user buys again from the Play Store. This is a new purchase with a new token and a SUBSCRIPTION_PURCHASED RTDN. You must acknowledge it; the outOfAppPurchaseContext field helps you link it to the previous subscription and user.

Inside your app, Google’s guide describes winning back users who cancelled by offering a re-signup screen (for example with a Reactivate button), either before expiry or after. Subscription offers can target eligible users with discounts; eligibility rules are set in the Play Console.

Refunds, voided purchases and chargebacks

When a purchase is refunded or charged back, it is voided. You receive a voidedPurchaseNotification RTDN with the purchase token, order ID, productType and refundType (full refund or quantity-based partial refund). Google’s lifecycle guide adds that a subscription charged back, or revoked by your backend with purchases.subscriptionsv2.revoke, triggers SUBSCRIPTION_REVOKED, and you should remove access. The Voided Purchases API gives you more detail over a time range.

For chargebacks, Google lets you weigh in. When a chargeback needs developer review, Google Play sends a PendingRefundReviewNotification RTDN, and you have 24 hours to respond with the ReviewRefund API, giving a refund preference and any purchase usage evidence. Google records only your first call.

A checklist

  • RTDNs are delivered to your backend, and each one triggers a subscriptionsv2.get.
  • Grace period and account hold are on, with lengths chosen on purpose.
  • Access stays on during the grace period and stops during account hold.
  • showInAppMessages() is called at app launch.
  • Your settings screen and emails use the specific subscription deep link.
  • Restore and resubscribe purchases are handled and acknowledged.
  • Each purchase carries an obfuscated account ID, so you can match it to your user.
  • Voided purchases and chargeback review notifications are handled.

Doing this with NoChurn

Google keeps payments, retries, the grace period, account hold and the cancel button; NoChurn does not change that. NoChurn reads your real-time developer notifications, matches each subscription to your user through the obfuscated account ID, and puts grace periods, holds, cancellations, recoveries and voided purchases on the customer timeline and in a churn score from 0 to 100. Where Google allows it, it acts: messages in your app or by email linking to the Play subscription page, a cancel flow your app shows through the headless API before linking to Google Play, and win-back emails at day 30, 60 and 90 based on the cancel reason. See NoChurn + Google Play.

PROMPT

Read https://www.nochurn.sh/llms.txt,
then follow https://www.nochurn.sh/docs/quickstart/
to add NoChurn to this app. Use a test key
(nc_test_…) until I say we go live.

Stop leaking revenue.

  • Free until $300 MRR
  • No card needed
  • Live in 10 minutes
  • Never a cut of what we recover