Software Engineering
Web Push Subscriptions: Reconcile Browser and Server State
Keep push subscriptions, account associations and preferences consistent across logout, endpoint changes and failed delivery without assuming permanence.
In this article
A web push subscription is not a permanent address for a person. It belongs to a browser context and needs a lifecycle that accounts for user choice, account changes, subscription replacement, and delivery failure. Reconcile browser and server state instead of treating the first successful signup as complete forever.
MDN's PushSubscription documentation describes the endpoint, keys, expiration information, and unsubscribe operation. In particular, an absent expiration time is not evidence that delivery will work indefinitely. Your application still needs a way to handle changing state.
Model three states separately
Distinguish browser notification permission, the current push subscription, and the application's topic or account preferences. A user can allow notifications in the browser while opting out of a particular category in your product. One boolean cannot accurately represent all three.
Record the subscription's account association only when the user is authenticated through the normal application flow. Do not infer identity from the endpoint string or let a client attach a subscription to an arbitrary account identifier.
Keep endpoints and key material within the appropriate access boundary. They are operational delivery data, not useful public identifiers. Avoid placing full subscription payloads in analytics events or support screenshots that do not need them.
Create a user-understandable enrollment path
Explain what notifications the person will receive and let them choose the relevant categories. Request browser permission in the supported user interaction flow. Do not label an unsuccessful or dismissed request as an active subscription.
After the browser returns a subscription, register it with the server through an authenticated, validated request. Handle a server failure explicitly. Browser-side enrollment alone does not prove that the delivery service stored the record or attached it to the intended preferences.
Make retry behavior safe. If a user repeats the enrollment action after a network error, the server should reconcile the same current subscription rather than creating unlimited duplicate rows and duplicate notifications.
Reconcile on an appropriate return visit
When the user returns to the relevant settings or application flow, compare the browser's supported current subscription state with the server association. A server row can outlive the browser state; a browser subscription can also exist after a failed registration attempt.
Use the comparison to restore consistency under the user's current preferences, not to silently re-enable categories they turned off. The goal is accurate state, not maximum subscriber count.
If a subscription changes, retire or replace the previous association through a documented process. Keep enough audit information to diagnose duplicate delivery without retaining obsolete endpoints indefinitely for no clear purpose.
Define what logout means
On a shared device, a subscription associated with the previous account can expose information after logout. Decide whether logout removes the account association, unsubscribes the browser, or follows another explicit product policy. Test the actual result rather than assuming browser permission disappears with the session.
Use notifications that reveal only the information appropriate to that delivery context. A message can often say that an update is available and require authentication to view details. Do not embed private account content simply because the endpoint was registered while the user was logged in.
Test account switching. Enroll account A, log out, sign in as account B, and inspect both the server associations and observed delivery. The expected result should be written before the test so the team does not rationalize whatever behavior occurs.
Treat delivery responses as evidence with limits
Classify failures according to the push service's documented response semantics. A permanently invalid subscription needs a different action from a transient delivery problem. Do not delete every subscription after one timeout or retry an invalid endpoint indefinitely.
An accepted push request is not proof that a person saw a notification. Keep submitted, accepted, displayed where observable, and opened as distinct events. Avoid claiming exact readership from a server-side success count.
Use bounded retries for transient failures and prevent notification bursts after recovery. A delayed queue should respect expiry and relevance. Sending yesterday's urgent notification repeatedly can be worse than dropping an obsolete message under the documented policy.
Test opt-out end to end
Turn off a category, then verify that the server stops selecting the subscription for that category. If the user requests a complete unsubscribe, check both the browser operation and server cleanup. An interface saying “disabled” is not enough if a background job still reads the old row.
Our push-publishing authorization guide covers a different side of the system: who may send. Subscription lifecycle review focuses on who should receive, which preferences apply, and when an association should end.
Keep a synthetic test account and device matrix for permission denial, cleared browser data, logout, account switching, and registration failure. Re-run it when the service worker or account model changes.
Conclusion
Manage web push as changing browser, account, and preference state. Verify enrollment, reconcile subscriptions, define logout behavior, and test opt-out through the delivery selection path. A subscription without a known expiry is still a relationship that needs maintenance.