How Web Push Notifications Work Internally

You see notifications for new messages, order updates, or payment reminders.

It looks simple. Your backend sends a message and the user receives it.

In reality, the process involves many moving parts. Your backend never talks directly to the browser. Instead, it uses a Push Service.

Google Chrome uses Firebase Cloud Messaging. Firefox uses the Mozilla Push Service.

The workflow works like this:

Backend → Push Service → Browser → Service Worker → User

Here is how you build this system using React and Golang.

The Components

  1. Frontend (React): Requests permission and registers a Service Worker.
  2. Service Worker: A background script that lives in the browser. It handles events even when your website is closed.
  3. Backend (Golang): Stores subscriptions and sends encrypted messages.
  4. Push Service: The middleman that delivers the message to the browser.

The Subscription Flow

To send a message, you need a subscription.

  • The user grants permission.
  • The browser generates a subscription object containing an endpoint and security keys.
  • Your React app sends this object to your Golang backend.
  • Your backend saves it in a database.

You must use VAPID keys to identify your server. Use a public key for the frontend and a private key for the backend. Never share your private key.

The Implementation

In React, you register a Service Worker to listen for push events. This worker runs in the background. It receives the data and shows the notification to the user.

In Golang, you use a library to handle encryption and VAPID authentication. Your server reads the subscription from your database, encrypts the payload, and sends it to the browser push service.

Scaling for Production

A simple setup works for small projects. A large system needs more.

  • Handle multiple devices: One user might have a phone and a laptop. Store multiple subscriptions per user.
  • Clean up data: Subscriptions expire. If you get a 404 or 410 error, delete that subscription from your database.
  • Use Queues: For millions of users, use Kafka or a similar tool. This allows your system to process notifications asynchronously.
  • Implement retries: Use exponential backoff to handle network failures.

WebSockets are good for live chats when the user is active. Web Push is better for reaching users when the tab is closed.

Source: https://dev.to/chandu_bobbili_06/how-web-push-notifications-work-internally-implementing-with-react-golang-6m