Compare 6 push notification services side-by-side. Free tiers, platform support, multi-channel capabilities, and code examples to help you choose the right notification infrastructure.
From your server to the user's device in 5 steps
When and why to send push notifications
Order confirmations, shipping updates, payment receipts, password resets. High-priority, time-sensitive notifications that users expect immediately.
Promotions, flash sales, feature announcements, re-engagement. Segment users by behavior and send targeted messages to drive conversions.
New message alerts, friend requests, mentions, likes. Real-time notifications that keep users engaged with social and messaging features.
Price alerts, trade confirmations, balance changes, security alerts. Critical financial notifications where delivery speed and reliability matter most.
Turn notifications, match invites, tournament updates, live scores. Time-sensitive alerts that bring users back to your app at the right moment.
Agent task completions, approval requests, workflow status changes. Notify users when autonomous AI agents need attention or finish work.
Side-by-side comparison of all 6 push notification services
| Feature | OneSignal | FCM | Pusher Beams | Amazon SNS | Expo Push | Novu |
|---|---|---|---|---|---|---|
| Free Tier | Unlimited mobile push | Completely free | 1K devices/mo | 1M push/mo | Unlimited | 10K runs/mo |
| Starting Price | $19/mo | Free forever | ~$29/mo | $0.50/1M | Free | $30/mo |
| iOS (APNs) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Android (FCM) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Web Push | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ |
| ✓ (10K/mo free) | ✗ | ✗ | ∷ Basic | ✗ | ✓ (multi-provider) | |
| SMS | ∷ Paid only | ✗ | ✗ | ✓ | ✗ | ✓ (multi-provider) |
| In-App | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ (embeddable) |
| Segmentation | ✓ (6 free) | ∷ Via Analytics | ✗ | ✗ | ✗ | ✓ (topics) |
| A/B Testing | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
| Scheduling | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ (delay steps) |
| Rich Push | ✓ | ∷ Client-side | ✓ | ✓ | ✓ | ✓ |
| Analytics | ✓ (30-day free) | ✓ (BigQuery) | ∷ Basic | ∷ CloudWatch | ∷ Receipts | ✓ (activity feed) |
| Open Source | ✗ | ✗ | ✗ | ✗ | ∷ Client SDK | ✓ (self-host) |
Which channels each service supports natively
| Channel | OneSignal | FCM | Pusher Beams | Amazon SNS | Expo Push | Novu |
|---|---|---|---|---|---|---|
| iOS Push | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Android Push | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Web Push | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ |
| ✓ | ✗ | ✗ | ✓ | ✗ | ✓ | |
| SMS | ∷ | ✗ | ✗ | ✓ | ✗ | ✓ |
| In-App Inbox | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ |
| Slack | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ |
| Discord | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ |
| ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | |
| Live Activities (iOS) | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
Detailed breakdown of each push notification service
Full-stack customer engagement platform with unlimited free mobile push. Journey builder, A/B testing, segmentation, and multi-channel delivery including email, SMS, and in-app messaging.
Google's push notification infrastructure. Completely free at any scale, no caps. Supports iOS, Android, and web push. Deep integration with Firebase ecosystem (Analytics, A/B Testing, Remote Config).
Developer-focused push notification service by Pusher. Dead simple API for iOS, Android, and web push with hosted token management and authenticated user support.
AWS infrastructure for pub/sub messaging at massive scale. 1 million free mobile push per month, then $0.50 per million. Raw building block, not a user-facing notification platform.
Free push notification relay for Expo React Native apps. Abstracts APNs and FCM complexity into a single API. Send notifications with a simple HTTP POST, no server SDK required.
Open source notification infrastructure for all channels. Orchestrate push, email, SMS, in-app, and chat (Slack, Discord, Teams) in unified workflows. Self-host for free or use the cloud.
Choosing between turnkey solutions and building your own
| Aspect | Managed (OneSignal, Pusher) | Infrastructure (FCM, SNS) | Self-Hosted (Novu OSS) |
|---|---|---|---|
| Setup Time | Minutes | Hours | Hours (Docker) |
| Token Management | Handled for you | You manage | Provider-dependent |
| Segmentation | Built-in dashboard | Build your own | Topic-based |
| Analytics | Full dashboard | CloudWatch/BigQuery | Activity feed |
| Multi-channel | OneSignal: Yes | Push only | All channels |
| Cost at 1M users | $1,200+/mo | Free (FCM) / ~$5/mo (SNS) | Hosting costs only |
| Vendor Lock-in | High | Medium (Google/AWS) | None |
| Best For | Marketing teams, fast iteration | Engineering teams, AWS/GCP apps | Teams wanting full control |
Send your first push notification with each provider
# Send to all subscribers
curl -X POST https://onesignal.com/api/v1/notifications \
-H "Content-Type: application/json" \
-H "Authorization: Basic YOUR_REST_API_KEY" \
-d '{
"app_id": "YOUR_APP_ID",
"included_segments": ["All"],
"headings": {"en": "New Feature!"},
"contents": {"en": "Check out our latest update."},
"url": "https://yourapp.com/updates"
}'
const response = await fetch('https://onesignal.com/api/v1/notifications', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic YOUR_REST_API_KEY'
},
body: JSON.stringify({
app_id: 'YOUR_APP_ID',
included_segments: ['All'],
headings: { en: 'New Feature!' },
contents: { en: 'Check out our latest update.' }
})
});
const data = await response.json();
console.log(`Sent to ${data.recipients} devices`);
# Send to a specific device
curl -X POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT/messages:send \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-d '{
"message": {
"token": "DEVICE_FCM_TOKEN",
"notification": {
"title": "New Feature!",
"body": "Check out our latest update."
},
"data": {
"url": "https://yourapp.com/updates"
}
}
}'
import admin from 'firebase-admin';
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const message = {
notification: {
title: 'New Feature!',
body: 'Check out our latest update.'
},
token: 'DEVICE_FCM_TOKEN'
};
const response = await admin.messaging().send(message);
console.log('Message sent:', response);
# Send to a device interest (topic)
curl -X POST "https://YOUR_INSTANCE.pushnotifications.pusher.com/publish_api/v1/instances/YOUR_INSTANCE/publishes/interests" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-d '{
"interests": ["updates"],
"web": {
"notification": {
"title": "New Feature!",
"body": "Check out our latest update.",
"deep_link": "https://yourapp.com/updates"
}
},
"apns": {
"aps": {
"alert": {
"title": "New Feature!",
"body": "Check out our latest update."
}
}
},
"fcm": {
"notification": {
"title": "New Feature!",
"body": "Check out our latest update."
}
}
}'
import PushNotifications from '@pusher/push-notifications-server';
const beamsClient = new PushNotifications({
instanceId: 'YOUR_INSTANCE_ID',
secretKey: 'YOUR_SECRET_KEY'
});
await beamsClient.publishToInterests(['updates'], {
apns: {
aps: { alert: { title: 'New Feature!', body: 'Check out our latest update.' } }
},
fcm: {
notification: { title: 'New Feature!', body: 'Check out our latest update.' }
},
web: {
notification: { title: 'New Feature!', body: 'Check out our latest update.' }
}
});
# Send to a platform endpoint (single device)
aws sns publish \
--target-arn "arn:aws:sns:us-east-1:123456789:endpoint/GCM/MyApp/abc123" \
--message '{"GCM": "{\"notification\": {\"title\": \"New Feature!\", \"body\": \"Check out our latest update.\"}}"}' \
--message-structure json
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
const sns = new SNSClient({ region: 'us-east-1' });
// Send to a topic (broadcast)
const result = await sns.send(new PublishCommand({
TopicArn: 'arn:aws:sns:us-east-1:123456789:app-updates',
Message: JSON.stringify({
GCM: JSON.stringify({
notification: { title: 'New Feature!', body: 'Check out our latest update.' }
}),
APNS: JSON.stringify({
aps: { alert: { title: 'New Feature!', body: 'Check out our latest update.' } }
})
}),
MessageStructure: 'json'
}));
console.log('MessageId:', result.MessageId);
# Send to Expo push tokens (no auth needed)
curl -X POST https://exp.host/--/api/v2/push/send \
-H "Content-Type: application/json" \
-d '[{
"to": "ExponentPushToken[xxxxxxxx]",
"title": "New Feature!",
"body": "Check out our latest update.",
"data": {"url": "/updates"},
"sound": "default"
}]'
import { Expo } from 'expo-server-sdk';
const expo = new Expo();
const messages = [{
to: 'ExponentPushToken[xxxxxxxx]',
title: 'New Feature!',
body: 'Check out our latest update.',
data: { url: '/updates' },
sound: 'default'
}];
const chunks = expo.chunkPushNotifications(messages);
for (const chunk of chunks) {
const tickets = await expo.sendPushNotificationsAsync(chunk);
console.log('Tickets:', tickets);
}
# Trigger a workflow for a subscriber
curl -X POST https://api.novu.co/v1/events/trigger \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"name": "new-feature",
"to": {
"subscriberId": "user_123",
"email": "user@example.com"
},
"payload": {
"title": "New Feature!",
"body": "Check out our latest update.",
"url": "https://yourapp.com/updates"
}
}'
import { Novu } from '@novu/node';
const novu = new Novu('YOUR_API_KEY');
await novu.trigger('new-feature', {
to: {
subscriberId: 'user_123',
email: 'user@example.com'
},
payload: {
title: 'New Feature!',
body: 'Check out our latest update.',
url: 'https://yourapp.com/updates'
}
});
// Novu routes to push + email + in-app based on workflow config
curl -X POST https://onesignal.com/api/v1/notifications \
-H "Content-Type: application/json" \
-H "Authorization: Basic YOUR_REST_API_KEY" \
-d '{
"app_id": "YOUR_APP_ID",
"included_segments": ["Premium Users"],
"headings": {"en": "Exclusive Offer"},
"contents": {"en": "50% off premium features, today only!"},
"chrome_web_image": "https://example.com/promo.png",
"big_picture": "https://example.com/promo.png"
}'
import admin from 'firebase-admin';
// Subscribe device to topic
await admin.messaging().subscribeToTopic(
['token1', 'token2', 'token3'],
'premium-users'
);
// Send to all topic subscribers
const response = await admin.messaging().send({
topic: 'premium-users',
notification: {
title: 'Exclusive Offer',
body: '50% off premium features, today only!'
},
android: {
notification: { imageUrl: 'https://example.com/promo.png' }
},
apns: {
payload: { aps: { 'mutable-content': 1 } },
fcm_options: { image: 'https://example.com/promo.png' }
}
});
console.log('Sent to topic:', response);
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
const sns = new SNSClient({ region: 'us-east-1' });
// Publish to all topic subscribers (push + email + SQS + Lambda)
await sns.send(new PublishCommand({
TopicArn: 'arn:aws:sns:us-east-1:123456789:premium-users',
Subject: 'Exclusive Offer',
Message: JSON.stringify({
default: 'Exclusive offer: 50% off premium features!',
GCM: JSON.stringify({
notification: {
title: 'Exclusive Offer',
body: '50% off premium features, today only!',
image: 'https://example.com/promo.png'
}
}),
APNS: JSON.stringify({
aps: {
alert: { title: 'Exclusive Offer', body: '50% off premium features!' },
'mutable-content': 1
}
})
}),
MessageStructure: 'json'
}));
Monthly cost by number of active users
| Monthly Active Users | OneSignal | FCM | Pusher Beams | Amazon SNS* | Expo Push | Novu Cloud |
|---|---|---|---|---|---|---|
| 1,000 | Free | Free | Free | Free | Free | Free |
| 10,000 | $19 + $120 | Free | ~$29 | Free | Free | Free (10K runs) |
| 50,000 | $19 + $600 | Free | ~$99 | Free | Free | $30 + usage |
| 100,000 | $19 + $1,200 | Free | Custom | ~$2.50 | Free | $30 + usage |
| 500,000 | Custom | Free | Custom | ~$125 | Free | $250+ |
| 1,000,000 | Custom | Free | Custom | ~$250 | Free | Custom |
* Amazon SNS pricing is per notification sent ($0.50/million), not per user. Costs assume ~5 notifications per user per month. OneSignal prices at $0.012/MAU + $19 platform fee.
Pick the right push notification service for your use case
You need segmentation, A/B testing, journey automation, and analytics. You want a dashboard your marketing team can use without engineering.
You're already using Firebase Auth, Firestore, or Analytics. You want free push at any scale with deep Firebase ecosystem integration.
You want the fastest possible setup, a clean API, and don't need marketing features. Just reliable push delivery to your users.
You're building on AWS, need pub/sub fan-out to millions, and your engineering team will build the notification logic. Cost is critical.
You're building with Expo's managed or bare workflow. You want zero-config push that just works across iOS and Android.
You need push + email + SMS + in-app + Slack in one system with workflow orchestration, digests, and subscriber preferences. You want open source.
Frostbyte's Webhook Inspector lets you test, debug, and monitor webhook deliveries. Create inboxes instantly, no signup required.
Explore Frostbyte Tools