---
title: "Delete dead subscriptions and tokens at · Agent Wranglers"
url: https://agentwranglers.se/playbook/notifications/push-notifications/prune-push-subscriptions
updated: 2026-10-20
licence: "All rights reserved"
---

# Delete dead subscriptions and tokens at once

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
- Rule: Delete a push subscription or device token as soon as the service says it is gone. Remove tokens the app has not refreshed for 270 days.
- How: Web push services answer 404 or 410 for an expired subscription. APNs answers 410 `Unregistered`, and FCM answers 404 `UNREGISTERED`. Delete the row on these answers and never retry it. Store when each token was last refreshed by the app. Firebase treats Android tokens inactive for 270 days as expired, so delete tokens older than that. Retry 429 and 5xx answers with backoff, as in [retry with backoff](https://agentwranglers.se/playbook/api-design/reliability/retry-backoff).
- Check: Unsubscribe a staging browser and send to it. The row is gone after the send. A query finds no token with a last refresh older than 270 days.

Example:

```js
export async function pushOrPrune(row, message) {
  try {
    await sendPush(row.subscription, message);
  } catch (error) {
    if ([404, 410].includes(error.statusCode)) await db.pushSubscriptions.delete(row.id);
    else throw error;
  }
}
```

```python
from pywebpush import WebPushException

def push_or_prune(row, message):
    try:
        send_push(row.subscription, message)
    except WebPushException as error:
        if error.response is not None and error.response.status_code in (404, 410):
            db.push_subscriptions.delete(row.id)
        else:
            raise
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/push-notifications/prune-push-subscriptions`.

- Previous: [Give every push a lifetime and a topic](https://agentwranglers.se/playbook/notifications/push-notifications/push-ttl-and-collapse)
- Next: [Keep push payloads short and safe on a lock screen](https://agentwranglers.se/playbook/notifications/push-notifications/push-payload-privacy)
- [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
