---
title: "What does the Google Play notification SUBSCRIPTION_ON_HOLD mean?"
description: "SUBSCRIPTION_ON_HOLD (5) means a subscription entered account hold after a payment failure. Block access and ask the customer to fix their payment method."
url: https://revenuedot.app/docs/notifications/google-subscription-on-hold
---

# What does the Google Play notification SUBSCRIPTION_ON_HOLD mean?

The Google Play notification SUBSCRIPTION_ON_HOLD means a renewal payment failed and the subscription is now in account hold, so access should stop.

## Quick facts

| | |
|---|---|
| Notification | `subscriptionNotification.notificationType` 5, `SUBSCRIPTION_ON_HOLD` |
| Where | Google Play real-time developer notifications (Pub/Sub, `DeveloperNotification`) |
| Sent by | Google Play, as a Cloud Pub/Sub push to your endpoint |
| What Google says | A subscription has entered account hold, if account hold is enabled. |

## What triggers it

- A renewal payment failed and any grace period has ended. Account hold then begins. Google's default is 60 days minus the grace period.
- A subscription resuming from a pause with a failed payment goes straight into account hold.
- During hold the `expiryTime` stays in the past and the customer should not have access.

## What your server should do

1. Do not trust the message for the state. Google says a notification only tells you the purchase state changed; call the Google Play Developer API (`purchases.subscriptionsv2.get`) with the purchase token to get the full state.
2. Block access to the subscription while it is on hold.
3. Ask the customer to fix their payment method. Google tells customers too.
4. When they do, you get `SUBSCRIPTION_RECOVERED` with the same purchase token. If they do not, the subscription is cancelled and expires.
5. Answer 2xx once you have handled the message, and skip a `messageId` you have seen: Google recommends checking the uniqueness of message IDs so a redelivery does not make a second API call.

## Example

```javascript
// A Pub/Sub push body: the notification is base64 JSON in message.data.
const body = { message: { messageId: "136969346945", data: Buffer.from(JSON.stringify({"version":"1.0","packageName":"com.example.app","eventTimeMillis":"1790800914000","subscriptionNotification":{"version":"1.0","notificationType":5,"purchaseToken":"PURCHASE_TOKEN"}})).toString("base64") } };

function decide(body) {
  const n = JSON.parse(Buffer.from(body.message.data, "base64").toString("utf8"));
  if (!(n.subscriptionNotification?.notificationType === 5)) return "ignore";
  return "block access, ask the customer to fix their payment method";
}

console.log(decide(body));
```

*Run-checked: `npm run check:snippets` runs this snippet with Node and compares its output with `block access` (checked 2026-10-03).*

## How RevenueDot handles it

RevenueDot answers every handled message with 2xx and every temporary failure with 5xx so Pub/Sub redelivers it. For subscription types it re-reads the subscription from Google with `purchases.subscriptionsv2.get` and applies that state, and it acknowledges a new purchase if the app has not. A purchase RevenueDot has not seen is applied only when the app's **Track new purchases from server-to-server notifications** setting is on. RevenueDot stores a billing issue and ends access now. It sends `BILLING_ISSUE` and a `CANCELLATION` with `cancel_reason: BILLING_ERROR`, and the scheduler sends `EXPIRATION` with `expiration_reason: BILLING_ERROR`. A recovery later comes out as `RENEWAL`.

## Related

- [What does the Google Play notification SUBSCRIPTION_IN_GRACE_PERIOD mean?](https://revenuedot.app/docs/notifications/google-subscription-in-grace-period.md)
- [What does the Google Play notification SUBSCRIPTION_RECOVERED mean?](https://revenuedot.app/docs/notifications/google-subscription-recovered.md)
- [What does the Google Play notification SUBSCRIPTION_EXPIRED mean?](https://revenuedot.app/docs/notifications/google-subscription-expired.md)
- [Which webhook events does RevenueDot send?](https://revenuedot.app/docs/api/webhook-events.md)
- [Set up Google Play notifications in RevenueDot](https://revenuedot.app/docs/guides/google-play.md)

## Source

- [Google: Real-time developer notifications reference guide](https://developer.android.com/google/play/billing/rtdn-reference)
- [Google: Subscription lifecycle](https://developer.android.com/google/play/billing/lifecycle/subscriptions)
- [RevenueDot server: stores/google/notifications.ts (how the message is received)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/stores/google/notifications.ts)
- [RevenueDot server: stores/google/sync.ts (how the purchase is re-read and applied)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/stores/google/sync.ts)
- [RevenueDot server: stores/google/map.ts (how Google's state becomes a stored purchase)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/stores/google/map.ts)
- [RevenueDot core: events.ts (how a change becomes a webhook event)](https://github.com/revenuedot/revenuedot/blob/main/packages/core/src/events.ts)
- [RevenueDot server: services/tick.ts (the scheduled EXPIRATION)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/services/tick.ts)

Checked: 2026-10-03
