402 lines
10 KiB
Markdown
402 lines
10 KiB
Markdown
|
|
# Push Notification Service Alternatives to Firebase
|
||
|
|
|
||
|
|
This document outlines alternatives to Firebase Cloud Messaging (FCM) for push notifications in the ASLE platform.
|
||
|
|
|
||
|
|
## Current Implementation
|
||
|
|
|
||
|
|
The project currently uses:
|
||
|
|
- **Backend**: `firebase-admin` for sending notifications via FCM
|
||
|
|
- **Mobile**: `react-native-push-notification` for receiving notifications
|
||
|
|
|
||
|
|
## Alternative Services
|
||
|
|
|
||
|
|
### 1. **OneSignal** ⭐ Recommended
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Free tier: 10,000 subscribers, unlimited notifications
|
||
|
|
- ✅ Easy integration with React Native
|
||
|
|
- ✅ Web dashboard for analytics and targeting
|
||
|
|
- ✅ Supports iOS, Android, Web, and email
|
||
|
|
- ✅ Rich notification features (images, buttons, actions)
|
||
|
|
- ✅ Segmentation and targeting
|
||
|
|
- ✅ A/B testing
|
||
|
|
- ✅ Good documentation
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ Requires OneSignal SDK in mobile app
|
||
|
|
- ⚠️ Data stored on OneSignal servers
|
||
|
|
|
||
|
|
**Implementation:**
|
||
|
|
```bash
|
||
|
|
# Backend
|
||
|
|
npm install onesignal-node
|
||
|
|
|
||
|
|
# Mobile
|
||
|
|
npm install react-native-onesignal
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost:** Free up to 10K subscribers, then $9/month for 10K-100K
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. **Pusher Beams** (formerly Pusher)
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Simple REST API
|
||
|
|
- ✅ Good for real-time features
|
||
|
|
- ✅ WebSocket support
|
||
|
|
- ✅ Free tier: 2,000 devices
|
||
|
|
- ✅ Good for multi-platform apps
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ Smaller community than Firebase/OneSignal
|
||
|
|
- ⚠️ Less feature-rich than competitors
|
||
|
|
|
||
|
|
**Implementation:**
|
||
|
|
```bash
|
||
|
|
# Backend
|
||
|
|
npm install @pusher/push-notifications-server
|
||
|
|
|
||
|
|
# Mobile
|
||
|
|
npm install @pusher/push-notifications-react-native
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost:** Free for 2K devices, then $49/month for 10K devices
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. **Amazon SNS (Simple Notification Service)**
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Highly scalable (AWS infrastructure)
|
||
|
|
- ✅ Pay-per-use pricing
|
||
|
|
- ✅ Supports SMS, email, push, and more
|
||
|
|
- ✅ Direct integration with AWS services
|
||
|
|
- ✅ No subscriber limits
|
||
|
|
- ✅ Enterprise-grade reliability
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ More complex setup
|
||
|
|
- ⚠️ Requires AWS account and configuration
|
||
|
|
- ⚠️ Less user-friendly than Firebase/OneSignal
|
||
|
|
- ⚠️ No built-in analytics dashboard
|
||
|
|
|
||
|
|
**Implementation:**
|
||
|
|
```bash
|
||
|
|
# Backend
|
||
|
|
npm install @aws-sdk/client-sns
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost:** $0.50 per million requests, very cost-effective at scale
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. **Airship (formerly Urban Airship)**
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Enterprise-focused
|
||
|
|
- ✅ Advanced segmentation
|
||
|
|
- ✅ Rich analytics
|
||
|
|
- ✅ A/B testing
|
||
|
|
- ✅ Multi-channel (push, SMS, email, in-app)
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ Expensive for small apps
|
||
|
|
- ⚠️ Complex setup
|
||
|
|
- ⚠️ Overkill for simple use cases
|
||
|
|
|
||
|
|
**Cost:** Custom pricing (typically $500+/month)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 5. **Native Platform APIs (APNs + FCM Direct)**
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ No third-party dependency
|
||
|
|
- ✅ Full control
|
||
|
|
- ✅ No per-notification costs
|
||
|
|
- ✅ Direct integration
|
||
|
|
- ✅ Privacy-friendly (no data sent to third parties)
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ More complex implementation
|
||
|
|
- ⚠️ Need to manage both iOS (APNs) and Android (FCM) separately
|
||
|
|
- ⚠️ No built-in analytics
|
||
|
|
- ⚠️ Need to handle token management yourself
|
||
|
|
|
||
|
|
**Implementation:**
|
||
|
|
```bash
|
||
|
|
# Backend - For APNs (iOS)
|
||
|
|
npm install apn
|
||
|
|
|
||
|
|
# Backend - For FCM (Android) - can use firebase-admin or native HTTP
|
||
|
|
# Already have firebase-admin, but can use direct HTTP API
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost:** Free (only infrastructure costs)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 6. **Expo Push Notifications**
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Perfect if using Expo
|
||
|
|
- ✅ Simple setup
|
||
|
|
- ✅ Free tier
|
||
|
|
- ✅ No server needed for basic use
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ Only works with Expo
|
||
|
|
- ⚠️ Limited features
|
||
|
|
- ⚠️ Not suitable for production at scale
|
||
|
|
|
||
|
|
**Cost:** Free
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 7. **Pusher Channels** (Real-time + Push)
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Good for apps needing both real-time and push
|
||
|
|
- ✅ WebSocket + Push in one service
|
||
|
|
- ✅ Simple API
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ More expensive than dedicated push services
|
||
|
|
- ⚠️ Less specialized for push notifications
|
||
|
|
|
||
|
|
**Cost:** $49/month for 200 concurrent connections
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 8. **SendGrid** (Twilio)
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- ✅ Part of Twilio ecosystem
|
||
|
|
- ✅ Good email + push integration
|
||
|
|
- ✅ Reliable infrastructure
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- ⚠️ More focused on email
|
||
|
|
- ⚠️ Push notifications are secondary feature
|
||
|
|
|
||
|
|
**Cost:** Custom pricing
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Comparison Matrix
|
||
|
|
|
||
|
|
| Service | Free Tier | Ease of Use | Analytics | Cost at Scale | Best For |
|
||
|
|
|---------|-----------|-------------|-----------|---------------|----------|
|
||
|
|
| **OneSignal** | 10K subs | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | $9/month | Most apps |
|
||
|
|
| **Pusher Beams** | 2K devices | ⭐⭐⭐⭐ | ⭐⭐⭐ | $49/month | Real-time apps |
|
||
|
|
| **AWS SNS** | Pay-per-use | ⭐⭐⭐ | ⭐⭐ | Very low | Enterprise/Scale |
|
||
|
|
| **Airship** | None | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | $500+/month | Enterprise |
|
||
|
|
| **Native APIs** | Free | ⭐⭐ | ⭐ | Infrastructure only | Privacy-focused |
|
||
|
|
| **Expo Push** | Free | ⭐⭐⭐⭐⭐ | ⭐⭐ | Free | Expo apps |
|
||
|
|
|
||
|
|
## Recommended Migration Path
|
||
|
|
|
||
|
|
### Option 1: OneSignal (Easiest Migration)
|
||
|
|
|
||
|
|
**Why:** Best balance of features, ease of use, and cost.
|
||
|
|
|
||
|
|
**Steps:**
|
||
|
|
1. Install OneSignal SDK in mobile app
|
||
|
|
2. Replace `PushNotificationService` with OneSignal service
|
||
|
|
3. Update backend to use OneSignal REST API
|
||
|
|
4. Migrate device tokens
|
||
|
|
|
||
|
|
**Code Example:**
|
||
|
|
```typescript
|
||
|
|
// backend/src/services/onesignal.ts
|
||
|
|
import axios from 'axios';
|
||
|
|
|
||
|
|
export class OneSignalService {
|
||
|
|
private appId: string;
|
||
|
|
private apiKey: string;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.appId = process.env.ONESIGNAL_APP_ID!;
|
||
|
|
this.apiKey = process.env.ONESIGNAL_API_KEY!;
|
||
|
|
}
|
||
|
|
|
||
|
|
async sendNotification(notification: PushNotification): Promise<void> {
|
||
|
|
await axios.post(
|
||
|
|
'https://onesignal.com/api/v1/notifications',
|
||
|
|
{
|
||
|
|
app_id: this.appId,
|
||
|
|
include_player_ids: [notification.token],
|
||
|
|
headings: { en: notification.title },
|
||
|
|
contents: { en: notification.body },
|
||
|
|
data: notification.data,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
Authorization: `Basic ${this.apiKey}`,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Option 2: AWS SNS (Most Scalable)
|
||
|
|
|
||
|
|
**Why:** Best for high-scale applications, pay-per-use pricing.
|
||
|
|
|
||
|
|
**Steps:**
|
||
|
|
1. Set up AWS SNS topics
|
||
|
|
2. Create platform applications for iOS/Android
|
||
|
|
3. Replace service with AWS SNS client
|
||
|
|
4. Handle APNs and FCM through SNS
|
||
|
|
|
||
|
|
**Code Example:**
|
||
|
|
```typescript
|
||
|
|
// backend/src/services/sns.ts
|
||
|
|
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
|
||
|
|
|
||
|
|
export class SNSService {
|
||
|
|
private sns: SNSClient;
|
||
|
|
private iosPlatformArn: string;
|
||
|
|
private androidPlatformArn: string;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.sns = new SNSClient({ region: process.env.AWS_REGION });
|
||
|
|
this.iosPlatformArn = process.env.AWS_SNS_IOS_ARN!;
|
||
|
|
this.androidPlatformArn = process.env.AWS_SNS_ANDROID_ARN!;
|
||
|
|
}
|
||
|
|
|
||
|
|
async sendNotification(notification: PushNotification, platform: 'ios' | 'android'): Promise<void> {
|
||
|
|
const platformArn = platform === 'ios' ? this.iosPlatformArn : this.androidPlatformArn;
|
||
|
|
|
||
|
|
await this.sns.send(new PublishCommand({
|
||
|
|
TargetArn: platformArn,
|
||
|
|
Message: JSON.stringify({
|
||
|
|
default: notification.body,
|
||
|
|
APNS: JSON.stringify({
|
||
|
|
aps: {
|
||
|
|
alert: {
|
||
|
|
title: notification.title,
|
||
|
|
body: notification.body,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
...notification.data,
|
||
|
|
}),
|
||
|
|
GCM: JSON.stringify({
|
||
|
|
notification: {
|
||
|
|
title: notification.title,
|
||
|
|
body: notification.body,
|
||
|
|
},
|
||
|
|
data: notification.data,
|
||
|
|
}),
|
||
|
|
}),
|
||
|
|
MessageStructure: 'json',
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Option 3: Native APIs (Most Control)
|
||
|
|
|
||
|
|
**Why:** No third-party dependency, full control, privacy-friendly.
|
||
|
|
|
||
|
|
**Steps:**
|
||
|
|
1. Keep FCM for Android (or use direct HTTP API)
|
||
|
|
2. Add APNs for iOS
|
||
|
|
3. Create unified service wrapper
|
||
|
|
4. Handle token management
|
||
|
|
|
||
|
|
**Code Example:**
|
||
|
|
```typescript
|
||
|
|
// backend/src/services/native-push.ts
|
||
|
|
import apn from 'apn';
|
||
|
|
import axios from 'axios';
|
||
|
|
|
||
|
|
export class NativePushService {
|
||
|
|
private apnProvider: apn.Provider | null = null;
|
||
|
|
private fcmServerKey: string;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
// Initialize APNs for iOS
|
||
|
|
if (process.env.APNS_KEY_ID && process.env.APNS_TEAM_ID) {
|
||
|
|
this.apnProvider = new apn.Provider({
|
||
|
|
token: {
|
||
|
|
key: process.env.APNS_KEY_PATH!,
|
||
|
|
keyId: process.env.APNS_KEY_ID!,
|
||
|
|
teamId: process.env.APNS_TEAM_ID!,
|
||
|
|
},
|
||
|
|
production: process.env.NODE_ENV === 'production',
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
this.fcmServerKey = process.env.FCM_SERVER_KEY!;
|
||
|
|
}
|
||
|
|
|
||
|
|
async sendToIOS(token: string, notification: PushNotification): Promise<void> {
|
||
|
|
if (!this.apnProvider) throw new Error('APNs not configured');
|
||
|
|
|
||
|
|
const apnNotification = new apn.Notification();
|
||
|
|
apnNotification.alert = {
|
||
|
|
title: notification.title,
|
||
|
|
body: notification.body,
|
||
|
|
};
|
||
|
|
apnNotification.topic = process.env.APNS_BUNDLE_ID!;
|
||
|
|
apnNotification.payload = notification.data;
|
||
|
|
apnNotification.sound = 'default';
|
||
|
|
|
||
|
|
await this.apnProvider.send(apnNotification, token);
|
||
|
|
}
|
||
|
|
|
||
|
|
async sendToAndroid(token: string, notification: PushNotification): Promise<void> {
|
||
|
|
await axios.post(
|
||
|
|
'https://fcm.googleapis.com/fcm/send',
|
||
|
|
{
|
||
|
|
to: token,
|
||
|
|
notification: {
|
||
|
|
title: notification.title,
|
||
|
|
body: notification.body,
|
||
|
|
},
|
||
|
|
data: notification.data,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
Authorization: `key=${this.fcmServerKey}`,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Migration Checklist
|
||
|
|
|
||
|
|
- [ ] Choose alternative service
|
||
|
|
- [ ] Set up account/credentials
|
||
|
|
- [ ] Install SDKs/packages
|
||
|
|
- [ ] Create new service class
|
||
|
|
- [ ] Update mobile app to use new SDK
|
||
|
|
- [ ] Migrate device tokens
|
||
|
|
- [ ] Update environment variables
|
||
|
|
- [ ] Test on iOS and Android
|
||
|
|
- [ ] Update documentation
|
||
|
|
- [ ] Remove Firebase dependencies (if switching completely)
|
||
|
|
- [ ] Monitor notification delivery rates
|
||
|
|
|
||
|
|
## Recommendation
|
||
|
|
|
||
|
|
For the ASLE project, I recommend **OneSignal** because:
|
||
|
|
1. ✅ Easy migration from Firebase
|
||
|
|
2. ✅ Free tier covers most use cases
|
||
|
|
3. ✅ Excellent React Native support
|
||
|
|
4. ✅ Rich analytics and targeting
|
||
|
|
5. ✅ Good documentation and community
|
||
|
|
6. ✅ Cost-effective scaling
|
||
|
|
|
||
|
|
If you need maximum control and privacy, use **Native APIs** (APNs + FCM direct).
|
||
|
|
|
||
|
|
If you're already on AWS and need enterprise scale, use **AWS SNS**.
|
||
|
|
|