Prompt
How do I integrate push notifications into a SaaS backend?
Latest observation
Integrating push notifications into a SaaS backend usually means building a reliable pipeline that can:
- capture user/device subscriptions
- store and target them
- send notifications through a provider
- track delivery/engagement
- respect tenant isolation, preferences, and compliance
Here’s a practical way to design it.
1) Decide what kind of push you need
There are a few distinct channels:
- Web push: browsers via service workers (Chrome, Firefox, Edge, etc.)
- Mobile push: iOS/Android through APNs/FCM, usually via Firebase Cloud Messaging
- Desktop app push: often same as mobile/web depending on app stack
- In-app notifications: not push, but often built alongside for reliability
If you’re building a SaaS, you often need:
- web push for browser users
- mobile push if you have mobile apps
- fallback in-app/email for critical messages
2) Pick a push delivery provider
Common choices:
Web push
- Native Web Push Protocol
- Works with browser subscriptions directly
- You manage VAPID keys and sending
- OneSignal
- Easier setup, dashboard, segmentation
- Firebase Cloud Messaging
- Can do web + mobile, but web support depends on browser/service worker setup
Mobile push
- FCM for Android
- APNs for iOS
- Usually you use FCM as the aggregation layer, but APNs is still the underlying iOS transport
SaaS-friendly approach
If you want less operational burden:
- OneSignal or similar notification platform If you want more control:
- Direct integration with FCM/APNs/Web Push
3) Build your data model
At minimum, store:
Tenants
If your SaaS is multi-tenant, every notification object should belong to a tenant.
Users
Your application users.
Devices / push subscriptions
Store one or more subscriptions per user:
- browser endpoint + keys for web push
- FCM token for mobile
- platform info, app version, locale, last_seen, etc.
Example fields:
tenant_iduser_idchannel(web,ios,android)provider(fcm,apns,webpush)token_or_endpointp256dh,auth(for web push)device_idenabledlast_seen_atcreated_at,updated_at
Notification jobs
tenant_idevent_typetarget_user_idsor audience segmentpayloadstatusscheduled_atsent_at
Delivery logs
Useful for debugging and analytics:
- success/failure
- provider response
- error code
- retry count
4) Collect subscriptions from clients
Web push flow
- User opts in
- Frontend asks permission
- Service worker subscribes to push
- Client sends subscription payload to backend
- Backend stores it linked to the user
Frontend example steps:
- register service worker
- call
pushManager.subscribe() - send subscription JSON to API
Backend should verify the user is authenticated and attach the subscription to the correct tenant/user.
Mobile push flow
- App obtains push token from FCM/APNs
- App sends token to backend
- Backend stores token and platform info
Also handle:
- token refresh
- logout/uninstall cleanup if possible
5) Create a notification service in your backend
You want a dedicated module/service, not scattered push logic.
Typical responsibilities:
- validate targets
- render message templates
- choose the right subscriptions/tokens
- send through provider(s)
- handle retries/failures
- mark invalid tokens as stale
- queue jobs for async delivery
Architecture pattern:
- API layer creates notification request
- Queue/worker sends messages asynchronously
- Provider adapter handles FCM/APNs/Web Push specifics
This keeps your web request fast and makes delivery resilient.
6) Send notifications asynchronously
Do not send push notifications synchronously in your main request path.
Use:
- Sidekiq / Celery / BullMQ / Resque / SQS workers / background jobs
Flow:
- Business event occurs
- Backend creates notification record
- Enqueue job
- Worker fetches subscriptions and sends
- Worker logs result and retries on transient errors
This helps with:
- scale
- rate limits
- outages
- retries
- batching
7) Support multi-tenant isolation
In SaaS, this is critical.
Make sure:
- subscriptions are always scoped to a
tenant_id - notification jobs only query data within the tenant
- admins can only send to users in their own tenant
- analytics are tenant-scoped
If tenants can customize branding:
- store tenant-specific titles, icons, click URLs, and message templates
8) Respect notification preferences
Users should control:
- opt-in/opt-out
- notification categories
- quiet hours
- channel preferences
- frequency caps
Example categories:
- security alerts
- billing alerts
- product updates
- marketing
Good practice:
- default critical notifications on
- marketing notifications opt-in only
- allow unsubscribe per category
9) Handle provider-specific behavior
Web Push
- requires a service worker
- uses VAPID authentication
- payload size is limited
- browser support varies
FCM
- tokens can expire or rotate
- handle invalid tokens by removing them
- use platform-specific notification formatting if needed
APNs
- needs Apple credentials/certificates or tokens
- iOS background behavior can be restrictive
- payload structure must follow APNs rules
Your backend should normalize your app’s notification model into provider-specific payloads.
10) Design your notification payload
Keep the backend payload generic, then map to provider formats.
Example generic payload:
{
"type": "invoice_paid",
"title": "Invoice paid",
"body": "Your invoice #1234 has been paid.",
"data": {
"tenant_id": "t_123",
"invoice_id": "inv_1234",
"url": "/billing/invoices/1234"
}
}
Use data for routing inside your app. Avoid putting sensitive data in notification payloads.
11) Add observability
You’ll want:
- sent count
- delivered count if provider supports it
- open/click rate
- invalid token rate
- failures by provider
- retry counts
- queue latency
Log:
- notification ID
- tenant ID
- user ID
- provider response
- error reason
This is essential when debugging why users “aren’t getting alerts.”
12) Secure the system
Important safeguards:
- authenticate subscription registration
- authorize who can send notifications
- encrypt sensitive tokens at rest if possible
- never expose APNs/FCM credentials to clients
- validate all payloads
- limit notification frequency to avoid abuse
Also consider:
- audit logs for admin-sent notifications
- tenant quotas/rate limits
- CSRF protection on subscription endpoints if relevant
13) A simple reference architecture
Frontend
- asks for permission
- registers push subscription/token
- sends it to backend
Backend API
- stores subscription
- creates notification jobs from business events
Queue
- buffers notification jobs
Worker
- loads target subscriptions
- sends via provider adapter
- retries failures
- deletes stale tokens
Providers
- Web Push / FCM / APNs / OneSignal
14) Recommended implementation approach
If you want the fastest path:
Option A: Use OneSignal
Best if you want:
- quick setup
- dashboard
- segmentation
- analytics
- less infrastructure
Option B: Use FCM + APNs directly
Best if you want:
- maximum control
- lower vendor lock-in
- custom routing/business rules
Option C: Hybrid
- OneSignal for marketing/product updates
- direct provider integration for critical transactional notifications
15) Common pitfalls
- sending from the request thread
- not handling expired tokens
- not scoping by tenant
- mixing marketing and transactional notifications
- ignoring user preferences
- no retry policy
- storing raw tokens insecurely
- not testing browser/service worker behavior
- assuming push == delivery guarantee
16) Minimal backend flow example
- User logs in
- Frontend registers push token/subscription
- Backend stores it
- A SaaS event occurs, e.g. “invoice paid”
- Backend creates notification job
- Worker fetches all active subscriptions for that tenant/user
- Worker sends to provider
- Worker logs success/failure and removes invalid tokens
17) What I’d recommend for a typical SaaS
If you’re building a modern SaaS backend:
- Use a queue-based notification service
- Store subscriptions per tenant/user/device
- Support web push + mobile push separately
- Use templates and categories
- Add unsubscribe/preferences
- Track delivery and failures
- Start with one provider, abstract it behind an interface
If you want, I can also give you:
- a database schema for push notifications in a multi-tenant SaaS,
- a Node.js / Python / Go implementation example, or
- a step-by-step web push setup for browsers.