demo · v138

Subscription Lifecycle

A Web Push subscription moves through several states during its life — active, expired, permission-revoked, and (Chrome 138+) resubscribed. Click through each state transition below to see what events fire in the service worker, what the old and new subscription objects look like, and what your service worker needs to do.

Lifecycle state machine

No subscription
subscribe()
Active
key rotation
Key rotated
Expired
Permission revoked
permission re-granted (Chrome 138+)
Resubscribed
Select a state above to see details
What happens
Click any state in the diagram above.
Service worker code

Event log simulator

Click "Subscribe" to start the simulation…
// service-worker.js — Chrome 138+
self.addEventListener('pushsubscriptionchange', async (event) => {
  // oldSubscription: the expired/revoked endpoint
  // newSubscription: the fresh endpoint (may be null if subscribe failed)
  const { oldSubscription, newSubscription } = event;

  event.waitUntil(async function() {
    if (!newSubscription) {
      // Resubscription failed — notify your server endpoint is dead
      await fetch('/api/push/unregister', {
        method: 'POST',
        body: JSON.stringify({ endpoint: oldSubscription.endpoint })
      });
      return;
    }

    // Send new endpoint to your server so it can deliver future pushes
    await fetch('/api/push/update', {
      method: 'POST',
      body: JSON.stringify({
        old: oldSubscription.endpoint,
        new: newSubscription.toJSON()
      })
    });
  }());
});

see also