Agent Wranglers

Push notifications Required

Delete dead subscriptions and tokens at once

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 to do it

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.

Example

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;
  }
}
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

How to 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.

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.