Think of web push notifications like this:
Your Website -> Browser Company Server -> User Browser -> Notification PopupYour 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 = CustomerFlow:
Restaurant prepares food
↓
Delivery company picks it up
↓
Delivery company delivers to customerSimilarly:
Your server creates notification
↓
Browser push service receives it
↓
Browser delivers it to userThe Complete Flow
Step 1: User Visits Your Website
User opens:
https://example.comYour 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 SubscriptionIt 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 browserLike:
House Address:
Flat 202, DelhiBut digitally.
Example:
https://fcm.googleapis.com/fcm/send/abc123This 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:
| User | Endpoint |
|---|---|
| John | https://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 BrowserYour backend sends request to:
https://fcm.googleapis.com/fcm/send/abc123using code like:
webpush.sendNotification(subscription, payload);What Is FCM?
FCM means:
Firebase Cloud MessagingGoogle 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 GoogleGoogle 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 WorkerWhat 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 browserService 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 messageThink of Browser Push Service Like WhatsApp Servers
You do NOT send WhatsApp messages directly to another phone.
You send:
Your Phone -> WhatsApp Server -> Other PhoneSimilarly:
Your Server -> Google Push Server -> BrowserWhy 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 FCMGoogle 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 verification3 Prevent Fake Notifications
Without VAPID:
Anyone could send fake pushesWith VAPID:
Only authenticated servers can send notificationsWorking of VAPID
Step 1: You Generate VAPID Keys
You create:
Public Key
Private KeyExample:
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/SignatureStep 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:
- contacts push service
- creates subscription
- associates it with your pubic key
Example:
{
"endpoint": "https://fcm.googleapis.com/fcm/send/abc123"
}Google stores internally:
Subscription abc123 belongs to PUBLIC_KEY xyzThis 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 tokenThis 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_KEYThis creates:
Digital SignatureLike 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 KeyNow Google checks:
Can this signature be verified using this public key?If Yes:
Sender is authenticPush accepted.
If No:
Fake senderPush rejected.
Important Cryptography Idea
This is called:
Public-Key CryptographyRule:
Data signed with private key
can only be verified with matching public key



Join the discussion
Sign in with your account to post comments, reply to others, and participate in the conversation.
Login to Comment