Firebase Push Notification Setup
This document explains how push delivery works in the current BCI notification module and how to configure Firebase Cloud Messaging.
The backend now uses:
kreait/laravel-firebasekreait/firebase-php
Current Delivery Model
The notification module now does two separate things:
- creates in-app notification rows
- sends mobile push through Firebase FCM when Firebase push is enabled
This separation is important:
- inbox notifications do not depend on mobile push success
- push delivery status is tracked separately per recipient
Required Environment Variables
Add these values in .env:
FIREBASE_PUSH_ENABLED=true
FIREBASE_CREDENTIALS=storage/app/firebase.json
FIREBASE_ANDROID_PRIORITY=high
FIREBASE_ANDROID_SOUND=default
FIREBASE_ANDROID_CHANNEL_ID=bci_general
FIREBASE_APNS_PUSH_TYPE=alert
FIREBASE_APNS_PRIORITY=10
FIREBASE_APNS_TOPIC=com.your.bundle.id
FIREBASE_APNS_SOUND=default
The backend also accepts:
FIREBASE_CREDENTIALS_PATH=storage/app/firebase.json
Recommended convention:
- use
FIREBASE_CREDENTIALS - keep
FIREBASE_CREDENTIALS_PATHonly for compatibility with existing environments
Service Account Requirements
Use a Firebase service account JSON that contains:
project_idclient_emailprivate_key
The backend uses Firebase HTTP v1 API through the Kreait Firebase package.
Recommended Server File Location
Recommended path:
storage/app/firebase.json
Example:
FIREBASE_CREDENTIALS=storage/app/firebase.json
Queue Requirement
Push delivery is queued.
Do not expect push to work if the queue worker is not running.
Run:
php artisan queue:work
If you use Supervisor on production, keep a dedicated worker running continuously.
App Requirement
The mobile app must register a device token after login:
POST /api/app/notifications/device-token
Without a registered active device token:
- the notification still appears in the app inbox
- push delivery will fail for that recipient
Delivery Flow
Current backend flow:
- notification row is created in
notifications - recipient rows are created in
notification_recipients - push jobs are dispatched in queue chunks
- each job loads active device tokens for the recipient batch
- backend sends Firebase multicast batches of up to 500 device tokens per request
- recipient
delivery_statusis updated - parent notification
statusis recalculated from recipient results
Service Capabilities
The backend Firebase service now supports three message patterns:
- single token send
- multicast send with one shared payload
- batch send with different payloads per token
Current module usage:
- general/system notifications use queued recipient fan-out
- each push job currently uses multicast when the payload is the same for all tokens
- the batch method is available for future mixed-payload sends without adding another service
Batch Strategy
This is the current scale strategy:
- recipient rows are inserted in chunks
- push jobs are dispatched in larger recipient chunks
- each push job flattens active device tokens
- Firebase send uses multicast batches of up to
500tokens per call - heterogeneous batch sends also chunk at
500messages per FirebasesendAll()call
Why this matters:
- 50,000 members must not result in 50,000 synchronous controller calls
- the backend now avoids one HTTP request per token
- the batch size follows Firebase multicast limits
Delivery Status Meaning
Push Data Payload
Every Firebase push data payload includes string values for:
| Key | Notes |
|---|---|
notification_id |
Notification row id. |
type |
Notification type code, for example NEW_MEMBER_JOINED. |
source_type |
Related source model class when available. |
source_id |
Related source row id when available. |
Additional type-specific keys:
| Type | Extra keys |
|---|---|
NEW_MEMBER_JOINED |
member_id contains the newly joined member id. |
Recipient delivery_status
| Value | Meaning |
|---|---|
PENDING |
recipient row created, push job not finished yet |
SENT |
Firebase push succeeded, or push was bypassed because Firebase is disabled |
FAILED |
Firebase push failed for that recipient |
READ |
member opened/read the notification in app |
Parent notification status
| Value | Meaning |
|---|---|
PENDING |
at least one recipient is still pending |
SENT |
at least one recipient push succeeded and no recipients are pending |
FAILED |
all recipients failed or no eligible recipients existed |
Disabled Mode
If:
FIREBASE_PUSH_ENABLED=false
then:
- recipient rows are still created
- inbox still works
- push HTTP calls are skipped
- recipient status is treated as successful for internal flow testing
This mode is useful for local development before Firebase credentials are available.
Invalid Token Handling
When Firebase responds with invalid or unregistered token errors:
- the device token is marked inactive
- future push attempts will skip that token
This keeps the token table cleaner over time.
Images In Push
If a notification has an image:
- backend sends the CDN/public URL in the Firebase notification payload
Make sure the image URL is publicly accessible to the mobile OS push renderer.
Android and iOS Configuration
The backend now builds platform config from environment values.
Android
Configured through:
FIREBASE_ANDROID_PRIORITY=high
FIREBASE_ANDROID_SOUND=default
FIREBASE_ANDROID_COLOR=
FIREBASE_ANDROID_CHANNEL_ID=bci_general
FIREBASE_ANDROID_TTL=
iOS / APNS
Configured through:
FIREBASE_APNS_PUSH_TYPE=alert
FIREBASE_APNS_PRIORITY=10
FIREBASE_APNS_TOPIC=com.your.bundle.id
FIREBASE_APNS_SOUND=default
Important:
apns-push-type=alertis correct for visible notifications- do not use
backgroundunless the mobile app is intentionally sending silent/background-only pushes FIREBASE_APNS_TOPICmust match the iOS bundle identifier used in the app
Important Operational Notes
queue:workmust be running- Firebase credentials must be valid
- app must register device tokens
- mobile app must request notification permission from the OS
- mobile app must handle foreground/background push behavior itself
What This Backend Does Not Do
Current backend does not handle:
- mobile-side Firebase SDK setup
- Android notification channel creation
- iOS APNS entitlement setup
- foreground push rendering inside Flutter/React Native/native app
Those remain mobile app responsibilities.