To send push notifications to groups in FlutterFlow, use Firebase Cloud Messaging topics for broad opt-in groups, or query a Firestore user segment and call sendEachForMulticast via a Cloud Function. Topics are best for interests or regions; Firestore queries are best for behavior-based segments like 'users who haven't opened the app in 7 days.'
Two Patterns for Group Notifications
FlutterFlow's built-in push notification action sends to a single FCM token — one user at a time. For groups you need two additional techniques. FCM topics let a device subscribe to a named channel (e.g., 'promotions' or 'region-us-east'). When you publish to that topic, Firebase fans the message out to every subscriber automatically — no loop required. The second pattern uses a Cloud Function that queries Firestore for a matching segment (e.g., all users where plan == 'pro'), collects their FCM tokens, and calls the Admin SDK's sendEachForMulticast. Both patterns are triggered from FlutterFlow via a custom API call or Cloud Function action.
Prerequisites
- Firebase project connected to FlutterFlow with push notifications enabled
- FCM server key added to FlutterFlow (Settings > Push Notifications)
- Firebase Blaze plan if using Cloud Functions
- Users collection in Firestore with an fcmToken field updated on login
Step-by-step guide
Store the FCM token on every login
Store the FCM token on every login
Before you can target groups you need every user's current FCM token saved in Firestore. In FlutterFlow open your app's initial action flow (typically triggered on the splash or home page load). Add a Custom Action that calls FirebaseMessaging.instance.getToken() and writes the result into the current user's Firestore document under the field fcmToken. Also store a lastSeen timestamp and any segment fields such as plan, region, or interests as an array. This document becomes the source of truth for all group targeting.
1// Custom Action: updateFcmToken.dart2import 'package:firebase_messaging/firebase_messaging.dart';3import 'package:cloud_firestore/cloud_firestore.dart';4import 'package:firebase_auth/firebase_auth.dart';56Future updateFcmToken() async {7 final token = await FirebaseMessaging.instance.getToken();8 final uid = FirebaseAuth.instance.currentUser?.uid;9 if (uid != null && token != null) {10 await FirebaseFirestore.instance.collection('users').doc(uid).update({11 'fcmToken': token,12 'lastSeen': FieldValue.serverTimestamp(),13 });14 }15}Expected result: Every user document in Firestore has a populated fcmToken field after login.
Subscribe users to FCM topics based on preferences
Subscribe users to FCM topics based on preferences
FCM topics are the simplest broadcast mechanism. A device subscribes to a named string topic, and any message sent to that topic is delivered to all subscribers. In FlutterFlow create a Custom Action called subscribeToTopic. Call FirebaseMessaging.instance.subscribeToTopic(topicName). Trigger this action from your onboarding flow when users select interests (sports, deals, news) or when they opt into a role-based group (admins, beta-testers). Add matching unsubscribeFromTopic actions on your notification preferences screen so users can opt out without you needing to maintain a token list.
1// Custom Action: subscribeToTopic.dart2import 'package:firebase_messaging/firebase_messaging.dart';34Future subscribeToTopic(String topicName) async {5 await FirebaseMessaging.instance.subscribeToTopic(topicName);6}78Future unsubscribeFromTopic(String topicName) async {9 await FirebaseMessaging.instance.unsubscribeFromTopic(topicName);10}Expected result: Users are enrolled in one or more FCM topics. You can verify in Firebase Console > Cloud Messaging > Topics.
Build a notification preferences screen with per-topic toggles
Build a notification preferences screen with per-topic toggles
Give users control by building a Preferences page in FlutterFlow. Add a Column with one Row per topic: a Text label ('Promotions', 'New Features', 'Regional Updates') and a Toggle widget. Bind each Toggle's initial value to a boolean field on the user's Firestore document (e.g., notif_promotions). On the Toggle's On Changed action, first call the subscribeToTopic or unsubscribeFromTopic Custom Action depending on the new value, then update the matching Firestore field. This approach keeps server state and on-device subscriptions in sync, so you can also filter users in Cloud Functions using the Firestore field.
Expected result: Toggling a preference immediately subscribes or unsubscribes the device and updates Firestore.
Send to a topic via a Cloud Function
Send to a topic via a Cloud Function
Create a Firebase Cloud Function (Node.js) that accepts a topic name and message payload and uses the Admin SDK to publish. Deploy it and call it from FlutterFlow using a Custom API Call or the Cloud Function action. In FlutterFlow go to Settings > Cloud Functions, add your deployed function, map the topic, title, and body parameters, and trigger it from an admin screen or a backend scheduled task. Only admin users should be able to trigger this — add a Firebase security rule or check custom claims inside the function.
1// functions/index.js2const { onCall } = require('firebase-functions/v2/https');3const { getMessaging } = require('firebase-admin/messaging');4const { initializeApp } = require('firebase-admin/app');56initializeApp();78exports.sendToTopic = onCall(async (request) => {9 const { topic, title, body, data } = request.data;10 if (!request.auth?.token?.admin) {11 throw new Error('Unauthorized');12 }13 const message = {14 notification: { title, body },15 data: data || {},16 topic,17 };18 const response = await getMessaging().send(message);19 return { messageId: response };20});Expected result: Calling the function delivers a push notification to every device subscribed to that topic within seconds to minutes.
Send to a Firestore-queried segment with sendEachForMulticast
Send to a Firestore-queried segment with sendEachForMulticast
For dynamic segments not suitable for topics (e.g., 'users who purchased in the last 30 days'), use a Cloud Function that queries Firestore, collects up to 500 FCM tokens per batch, and calls sendEachForMulticast. Create a scheduled Cloud Function or an onCall function with an admin guard. Query your users collection with the desired filter, map results to their fcmToken fields, chunk into arrays of 500, and send. Log failed tokens and remove them from Firestore to keep your token list clean.
1// functions/sendToSegment.js2const { onCall } = require('firebase-functions/v2/https');3const { getMessaging } = require('firebase-admin/messaging');4const { getFirestore } = require('firebase-admin/firestore');56exports.sendToSegment = onCall(async (request) => {7 const { filter, title, body } = request.data;8 const db = getFirestore();9 let query = db.collection('users');10 if (filter.plan) query = query.where('plan', '==', filter.plan);11 if (filter.region) query = query.where('region', '==', filter.region);12 const snap = await query.get();13 const tokens = snap.docs14 .map(d => d.data().fcmToken)15 .filter(Boolean);16 const chunkSize = 500;17 let sent = 0;18 for (let i = 0; i < tokens.length; i += chunkSize) {19 const chunk = tokens.slice(i, i + chunkSize);20 const result = await getMessaging().sendEachForMulticast({21 tokens: chunk,22 notification: { title, body },23 });24 sent += result.successCount;25 }26 return { sent };27});Expected result: The function returns the number of successfully delivered messages and the segment receives the notification.
Complete working example
1const { onCall, onSchedule } = require('firebase-functions/v2/https');2const { getMessaging } = require('firebase-admin/messaging');3const { getFirestore } = require('firebase-admin/firestore');4const { initializeApp } = require('firebase-admin/app');56initializeApp();78// Send to FCM topic (admin only)9exports.sendToTopic = onCall(async (request) => {10 if (!request.auth?.token?.admin) throw new Error('Unauthorized');11 const { topic, title, body, data } = request.data;12 const response = await getMessaging().send({13 notification: { title, body },14 data: data || {},15 topic,16 });17 return { messageId: response };18});1920// Send to Firestore segment (admin only)21exports.sendToSegment = onCall(async (request) => {22 if (!request.auth?.token?.admin) throw new Error('Unauthorized');23 const { filter, title, body } = request.data;24 const db = getFirestore();25 let query = db.collection('users');26 if (filter?.plan) query = query.where('plan', '==', filter.plan);27 if (filter?.region) query = query.where('region', '==', filter.region);28 const snap = await query.get();29 const tokens = snap.docs.map(d => d.data().fcmToken).filter(Boolean);30 let sent = 0;31 const staleTokens = [];32 for (let i = 0; i < tokens.length; i += 500) {33 const chunk = tokens.slice(i, i + 500);34 const result = await getMessaging().sendEachForMulticast({35 tokens: chunk,36 notification: { title, body },37 });38 sent += result.successCount;39 result.responses.forEach((r, idx) => {40 if (!r.success && r.error?.code === 'messaging/registration-token-not-registered') {41 staleTokens.push(chunk[idx]);42 }43 });44 }45 // Clean up stale tokens46 if (staleTokens.length > 0) {47 const batch = db.batch();48 const staleSnap = await db.collection('users')49 .where('fcmToken', 'in', staleTokens.slice(0, 10)).get();50 staleSnap.docs.forEach(d => batch.update(d.ref, { fcmToken: null }));51 await batch.commit();52 }53 return { sent, staleRemoved: staleTokens.length };54});Common mistakes when sending Push Notifications to Groups of Users in FlutterFlow
Why it's a problem: Subscribing all users to all topics by default
How to avoid: Subscribe users only when they explicitly select an interest during onboarding or from a preferences screen. Default all topic subscriptions to off.
Why it's a problem: Sending FCM tokens directly from the FlutterFlow client to another user's device
How to avoid: Always send group notifications from a Cloud Function or a secure backend that holds the FCM server key. The client only triggers the function.
Why it's a problem: Not chunking tokens into batches of 500 for sendEachForMulticast
How to avoid: Slice the token array into chunks of 500 and loop, accumulating success counts as shown in the complete code.
Why it's a problem: Ignoring stale token cleanup after delivery
How to avoid: Check each response in sendEachForMulticast results and delete or null out any token that returns messaging/registration-token-not-registered.
Best practices
- Always use topics for static interest groups (sports, promotions) and Firestore queries for dynamic behavioral segments.
- Provide a notification preferences screen so users can opt out of individual topics without uninstalling.
- Rate-limit your admin send screen to prevent accidental duplicate broadcasts to large groups.
- Log every group send in a Firestore notifications_log collection with timestamp, topic, segment, and sent count for audit purposes.
- Test with Firebase's notification composer in the Firebase Console before building your admin UI — it lets you send to topics without any code.
- Use custom data payloads in addition to notification payloads so the app can route users to the correct screen on tap.
- Monitor FCM delivery rates in Firebase Console > Cloud Messaging > Analytics and set up alerts for sudden drops.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm building a FlutterFlow app and need to send push notifications to groups of users. Explain how to use Firebase Cloud Messaging topics for opt-in groups and sendEachForMulticast for Firestore-queried segments. Show me a Cloud Function in Node.js for each approach.
In my FlutterFlow project I need to subscribe users to FCM topics from a notification preferences screen. Write a Custom Action in Dart that calls FirebaseMessaging.instance.subscribeToTopic and another that calls unsubscribeFromTopic, then updates a boolean field in the user's Firestore document.
Frequently asked questions
How many users can I send to with FCM topics?
There is no documented hard limit on topic subscribers. FCM has handled topics with tens of millions of subscribers. Very large topics (millions) may take a few minutes to fully fan out.
Do FCM topic subscriptions persist if the user uninstalls and reinstalls the app?
No. Uninstalling clears the FCM token and all topic subscriptions. When the user reinstalls, your onboarding flow must re-subscribe them to their saved topics, which is why storing preferences in Firestore is important.
What is the difference between FCM topics and multicast?
Topics are managed on the FCM server — devices opt in and the server handles delivery. Multicast requires you to maintain and pass a list of up to 500 tokens per call. Topics are simpler for static groups; multicast is better for dynamic, query-based segments.
Can I send group notifications without the Firebase Blaze plan?
You can subscribe devices to FCM topics on the free Spark plan and send topic messages using the Firebase Console's notification composer. You only need the Blaze plan if you use Cloud Functions to send programmatically.
How do I create location-based notification groups?
Subscribe users to a region topic (e.g., 'region_us_west') based on their stored location in Firestore, or use geohash queries in a Cloud Function to build a token list. Update the subscription whenever the user changes their location preference.
What happens if I call sendEachForMulticast with an expired token?
The response for that token will have success: false and an error code of messaging/registration-token-not-registered. You should detect this and remove the stale token from Firestore to keep your token list accurate.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation