CLOSE
Updated on 07 May, 202624 mins read 52 views

Think of web push notifications like this:

Your Website -> Browser Company Server -> User Browser -> Notification Popup

Your website does not directly send notifications to the browser.

Instead:

  • Chrome uses Google servers
  • Firefox uses Mozilla servers
  • Safari uses Apple servers

These servers act like delivery agents.

Real-Life Analogy

Imagine:

You = Restaurant
Google/FCM = Delivery Company
User = Customer

Flow:

Restaurant prepares food
        ↓
Delivery company picks it up
        ↓
Delivery company delivers to customer

Similarly:

Your server creates notification
        ↓
Browser push service receives it
        ↓
Browser delivers it to user

The Complete Flow

Step 1: User Visits Your Website

User opens:

https://example.com

Your website asks:

"Can I send notifications?"

Browser popup appears:

Allow notifications/
[Allow] [Block]

If user clicks Allow, browser starts setting things up.

Step 2: Browser Creates a Push Subscription

This is the Most Important part.

The browser creates a special object called:

Push Subscription

It contains:

{
  "endpoint": "https://fcm.googleapis.com/fcm/send/abc123",
  "keys": {
    "p256dh": "...",
    "auth": "..."
  }
}

What Is This Endpoint?

The endpoint is basically:

The delivery address of this browser

Like:

House Address:
Flat 202, Delhi

But digitally.

Example:

https://fcm.googleapis.com/fcm/send/abc123

This means:

"If you want to send notifications to THIS browser, send them here."

Important:

This endpoint belogs to:

  • Chrome/Google
  • Firefox/Mozilla
  • Safari/Apple

Not your server.

Step 3: Your Website Sends Subscription to Your Backend

Frontend sends this object to your server.

Example:

fetch('/save-subscription', {
  method: 'POST',
  body: JSON.stringify(subscription)
});

Your backend stores it in database.

Example:

UserEndpoint
Johnhttps://fcm.googleapis.com/...

Step 4: Something Happens

Suppose:

  • User gets message
  • Order shipped
  • New comment arrives

Your beckend decides:

"I should notify the user."

Step 5: Your Server Sends Notification to Google/FCM

This is where people get confused.

Your server does NOT send notification directly to browser.

Instead:

Your Server
      ↓
Google FCM Server
      ↓
Chrome Browser

Your backend sends request to:

https://fcm.googleapis.com/fcm/send/abc123

using code like:

webpush.sendNotification(subscription, payload);

What Is FCM?

FCM means:

Firebase Cloud Messaging

Google runs it.

Chrome browsers stay connected to Google servers all the time.

So Google already knows:

  • where browser is
  • whether device is online
  • how to take browser efficiently

Why This Middle Layer Exists

Imagine every website directly connected to every browser.

Impossible.

Instead:

Browser keeps ONE connection with Google

Google handles delivery for millions of websites.

This:

  • saves battery
  • reduces internet usage
  • improves scalability

Step 5: Browser Receives Push

Google sends push to Chrome.

Chrome wakes up:

Service Worker

What Is Service Worker?

Service Worker is background JavaScript.

It runs EVEN when:

  • website closed
  • tab closed
  • browser minimized

Think of it like:

Background mini-app inside browser

Service Worker Receives Push

Example:

self.addEventListener('push', event => {
  console.log('Push received');
});

Browser says:

"Hey service worker, new notification arrived."

Step 7: Service Worker Shows Notification

Now service worker displays popup:

self.registration.showNotification("New Message", {
  body: "You got a message"
});

User sees:

🔔 New Message
You got a message

Think of Browser Push Service Like WhatsApp Servers

You do NOT send WhatsApp messages directly to another phone.

You send:

Your Phone -> WhatsApp Server -> Other Phone

Similarly:

Your Server -> Google Push Server -> Browser

Why Push Notifications Are Efficient

Without push:

  • browser repeatedly asks server

With push:

  • server sends only when needed

This saves:

  • battery
  • CPU
  • bandwidth

What Is the Usage of VAPID?

VAPID is used to identify and authenticate your server when sending web push notifications.

VAPID stands for:

Voluntary Application Server Identification

When your backend sends a push notification, it sends it to:

  • Google (Chrome)
  • Mozilla (Firefox)
  • Apple (Safari)

These companies need to know:

"Who is sending this push notification?"

VAPID provides that identity.

Without VAPID

Imagine anybody on the internet could send push notifications pretending to be your website.

That would cause:

  • spam
  • fake notifications
  • abuse
  • phising attacks

So push service require:

  • sender identification
  • authentication

VAPID Solves This Problem

Your server proves:

"I am the real owner of this application."

using:

  • Public Key
  • Private Key

Main Usage of VAPID

1 Identify Your Server

When sending notification:

Your Server -> Google FCM

Google checks:

"Which application server is this?"

VAPID answers that.

2 Authenticate Push Requests

Your server digitally signs requests using:

  • private key

Push service verifies signature using:

  • public key

Like:

Digital signature verification

3 Prevent Fake Notifications

Without VAPID:

Anyone could send fake pushes

With VAPID:

Only authenticated servers can send notifications

Working of VAPID

Step 1: You Generate VAPID Keys

You create:

Public Key
Private Key

Example:

const vapidKeys = webpush.generateVAPIDKeys();

Output:

Public Key:
BEl62i...

Private Key:
kXz91...

What These Keys Mean

Public Key:

Shared with browser.

It identifies your application.

Private Key:

Stored only on backend.

It signs push requests

Real-Life Analogy:

Public Key = Username
Private Key = Password/Signature

Step 2: Browser Uses Your Public Key

Frontend code:

registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: PUBLIC_KEY
});

Browser now knows:

"This subscription belongs to this application server."

What Browser Does Internally

Browser:

  1. contacts push service
  2. creates subscription
  3. associates it with your pubic key

Example:

{
  "endpoint": "https://fcm.googleapis.com/fcm/send/abc123"
}

Google stores internally:

Subscription abc123 belongs to PUBLIC_KEY xyz

This is very important.

Step 3: Your Backend Sends Notification

Now suppose user receives message.

Backend sends push:

webpush.sendNotification(subscription, payload);

What Happens Internally Here

Before sending request:

library creates:

JWT token

This token contains:

  • who is sending
  • expiration
  • audience

Example:

{
  "aud": "https://fcm.googleapis.com",
  "exp": 1710000000,
  "sub": "mailto:test@example.com"
}

Step 4: JWT Is Signed Using Private Key

Your backend signs JWT using:

PRIVATE_KEY

This creates:

Digital Signature

Like signing a legal document.

Why Signature Matters

Because only YOU have:

  • private key

So only you can create valid signature.

Step 5: Google Verifies Signature

Google receives:

Push Request
+ JWT Token
+ Public Key

Now Google checks:

Can this signature be verified using this public key?

If Yes:

Sender is authentic

Push accepted.

If No:

Fake sender

Push rejected.

Important Cryptography Idea

This is called:

Public-Key Cryptography

Rule:

Data signed with private key
can only be verified with matching public key

 

Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy