Push Notifications with Firebase
Ding! You Have a Message!
Open interactive version (quiz + challenge)Real-world analogy
Push notifications are like a doorbell. The user doesn't need to keep checking if someone's at the door — the doorbell (Firebase Cloud Messaging) rings and tells them! Your server pushes the button, Firebase rings the bell on their device.
What is it?
Push notifications let your server send messages directly to a user's device (phone or browser) without the user needing to be on your app. Firebase Cloud Messaging (FCM) is the most popular service for this.
Real-world relevance
Every app you use sends push notifications — WhatsApp messages, Instagram likes, Uber ride updates, news alerts. FCM handles billions of notifications daily for free.
Key points
- Firebase Cloud Messaging (FCM) — FCM is Google's free push notification service for Android, iOS, and web. It handles delivery infrastructure — just call an API with the message and target. Delivers billions of messages daily at no cost.
- Device Tokens — When a user installs your app, FCM assigns a unique device token. Store tokens in your database linked to each user. Provide the token when sending and FCM routes it to the exact device. Refresh regularly.
- Topic Subscriptions — Users subscribe to topics like news, deals, or sports. One API call to a topic delivers to all subscribers automatically. Perfect for broadcasting announcements, breaking news, or promotions to large groups.
- Background Processing — Send notifications through a Bull queue instead of directly in your API handler. Queue the job, return instantly, let a background worker call FCM. Keeps your API responsive even for thousands of messages.
- Data Payloads — Notifications carry custom data beyond title and body. Include fields like screen: orderDetails and orderId: 123 so tapping navigates to the right screen. Data payloads create rich, interactive experiences.
- Rich Notifications — Go beyond plain text with images, action buttons, and expandable content. Show product images, add Reply and Mark as Read buttons, or display delivery progress. Rich notifications boost user engagement.
- Notification Channels — Android requires notification channels so users control which types they receive. Create channels for messages, updates, and promotions with different importance levels. High-priority wakes the screen silently.
- Token Management — FCM tokens become invalid when users uninstall, clear data, or switch devices. Handle refresh events in your client app and update the server. Remove stale tokens when FCM returns errors to keep data clean.
- Notification Analytics — Track delivery rates, open rates, and click-through rates to measure engagement. FCM provides delivery receipts. Use this data to optimize send times, personalize content, and stop sending what users ignore.
- Silent Notifications — Send data-only messages without visible alerts to trigger background work. Use silent notifications to sync data, update cache, or refresh badge counts. Users see nothing, but your app stays current when opened.
Code example
// 1. Initialize Firebase Admin SDK 🔧
import * as admin from 'firebase-admin';
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
// 2. Send to a specific device 📱
async function sendToDevice(token: string, title: string, body: string) {
await admin.messaging().send({
token: token, // device's unique FCM token
notification: {
title,
body,
},
data: {
// Custom data your app can read
screen: 'notifications',
actionId: '12345',
},
});
}
// 3. Send to a topic (all subscribers) 📢
async function sendToTopic(topic: string, title: string, body: string) {
await admin.messaging().send({
topic: topic, // e.g., 'new-properties', 'deals'
notification: { title, body },
});
}
// 4. In NestJS — queue it! 🎯
@Injectable()
export class NotificationService {
constructor(
@InjectQueue('notifications') private notifQueue: Queue
) {}
async notifyUser(userId: string, message: string) {
const user = await this.prisma.user.findUnique({
where: { id: userId },
select: { fcmTokens: true },
});
// Queue notification for each device
for (const token of user.fcmTokens) {
await this.notifQueue.add('push', {
token,
title: 'New Update!',
body: message,
});
}
}
}Line-by-line walkthrough
- 1. 1. Initialize Firebase Admin SDK 🔧
- 2. Importing required dependencies
- 3.
- 4.
- 5.
- 6.
- 7.
- 8. 2. Send to a specific device 📱
- 9. Declaring a function
- 10. Waiting for an async operation to complete
- 11.
- 12.
- 13.
- 14.
- 15. Closing block
- 16.
- 17. Custom data your app can read
- 18.
- 19.
- 20. Closing block
- 21.
- 22. Closing block
- 23.
- 24. 3. Send to a topic (all subscribers) 📢
- 25. Declaring a function
- 26. Waiting for an async operation to complete
- 27.
- 28.
- 29.
- 30. Closing block
- 31.
- 32. 4. In NestJS — queue it! 🎯
- 33. Decorator that adds metadata or behavior
- 34. Exporting for use in other files
- 35.
- 36. Decorator that adds metadata or behavior
- 37.
- 38.
- 39.
- 40. Declaring a variable
- 41.
- 42.
- 43.
- 44.
- 45. Queue notification for each device
- 46. Loop iteration
- 47. Waiting for an async operation to complete
- 48.
- 49.
- 50.
- 51.
- 52. Closing block
- 53. Closing block
- 54. Closing block
Spot the bug
async sendNotification(userId: string, msg: string) {
const user = await this.prisma.user.findUnique({ where: { id: userId } });
await admin.messaging().send({
token: user.fcmToken,
notification: { title: "Update", body: msg },
});
}Need a hint?
What if the user doesn't exist or has no FCM token?
Show answer
No null check for user or fcmToken. If user is null, accessing user.fcmToken crashes. Fix: add if (!user) throw new NotFoundException(); if (!user.fcmToken) return;
Explain like I'm 5
Push notifications are like a doorbell. You're playing inside and someone rings the bell to tell you something like 'Your pizza is here!' You don't have to keep opening the door to check - the doorbell tells you!
Fun fact
Firebase Cloud Messaging is completely FREE with no message limit. Google doesn't charge you whether you send 1 notification or 1 billion. That's pretty generous for a trillion-dollar company! 💰
Hands-on challenge
Create a Firebase project at console.firebase.google.com, get a server key, and send a test notification using the Firebase console's built-in testing tool!
More resources
- Firebase Cloud Messaging (Firebase Official)
- FCM Architecture Overview (Firebase Official)
- Firebase Push Notifications (Fireship)