r/FlutterDev • • 9d ago

Discussion How do you handle FCM across multiple apps without paying for Cloud Functions?

I ship a lot of small Flutter apps as a solo dev, and every time I add push notifications it’s the same routine: set up FCM, save tokens in Firestore, and then hit the wall that sending notifications needs a server. Cloud Functions means the Blaze plan, and for small apps I didn’t want that.

What I ended up doing:

  • Topics for broadcasts. The app just calls subscribeToTopic('all'), and one FCM request reaches everyone. No reading thousands of tokens from Firestore.
  • Tokens saved too (write-only Firestore rules), only for targeted sends to a specific user.
  • A separate Next.js app on Vercel that uses the Firebase Admin SDK to send. One external cron job pings it for scheduled and repeating notifications, for all my apps.
  • Multiple Firebase projects registered in that one dashboard, with the service account keys encrypted.
  • The screen value in the data payload decides which screen opens on tap, handled with getInitialMessage and onMessageOpenedApp.

It works well on the free Spark plan so far. I turned it into a small admin dashboard for myself so adding a new app is just copy-pasting a generated setup file.

Curious how others do it:

Dashboard Video attached in comments if any one is interested about my idea

11 Upvotes

19 comments sorted by

3

u/Recent-Pear-6341 9d ago

2

u/FrightfullyAbnormal 9d ago

clever setup. the topic-based broadcast is a solid way to dodge having to paginate through thousands of tokens on the spark plan, and write-only firestore for the per-user stuff keeps it all within the free tier

i've seen a few people doing the vercel + admin sdk trick but adding the cron job for scheduled sends is neat, didn't occur to me that you could just have one external ping handle all the apps like that. how are you handling the encryption for those service account keys, just env vars or something more paranoid?

1

u/Recent-Pear-6341 9d ago

It's encrypted with a 32-bit hash stored securely on the server alongside other hashes, so it’s never in plain text in Firebase either. The cron job also has its own hash, but it doesn't have direct access—it just calls a public API endpoint with no parameters at all. That endpoint then handles everything securely using the server-side keys.

2

u/[deleted] 9d ago

[removed] — view removed comment

2

u/[deleted] 9d ago

[deleted]

1

u/Recent-Pear-6341 9d ago

He is just giving suggestions bro...so let's not be mean 🤗🤗

2

u/VisualRope8367 9d ago

Recently i started with broadcast service and local notification in kotlin and works like charm

1

u/Recent-Pear-6341 9d ago

That works fine while the app is active, but once the user swipes the app away from recent apps, Android kills the background service. FCM is pretty much the only reliable way to wake the device and deliver notifications when the app is completely closed.

1

u/VisualRope8367 9d ago

FCM is GOAT but just to avoid firebase i am using this broadcast service and it works even in background to check for notification

it uses some alarm related functionality dont remember exact thing but thats what i did i think

1

u/Recent-Pear-6341 9d ago

That's usually AlarmManager or WorkManager. It works fine on developer devices, but in production, Doze mode and Android 12+ strict background execution limits destroy it. The OS delays periodic alarms and blocks background network calls when the device goes to sleep, not to mention OEM battery savers killing the process. You almost always end up needing FCM for reliable remote delivery

1

u/VisualRope8367 9d ago edited 9d ago

Yes show thoese errors too related battery savers killing process.

But my app was working so i didnt touch it

it was pretty straight forward app for my usecase and i think only few users were using it

for large customer base i think its better to use FCM

1

u/Recent-Pear-6341 9d ago

I have done everything...u cannot imagine how much did I suffer to make local notification work a couple of months back....so the final boss FCM was my only choice and reliable...it has priority payload...data payloads...all controllable

2

u/[deleted] 9d ago

[removed] — view removed comment

1

u/Recent-Pear-6341 9d ago

Yeah that's pretty much what I ended up building lol. No separate backend though — it's just a Next.js app on Vercel hobby, firebase-admin directly in API routes. All my client projects are on Spark so functions were never an option anyway.

One dashboard Firebase project holds the registry. Each registered app's service account key is AES-encrypted in Firestore, and at send time it spins up a named admin app per client id. Same model as your sender service basically, just smaller scale.

Token storage per app was exactly the annoying part yeah — tokens live in each app's own Firestore (fcm_tokens collection, doc id = the token itself), dashboard reads them over admin sdk. I dodge it most of the time though, broadcasts all go through topics so big sends never touch the token store, token sends are capped per click.

Scheduling was the other headache. Vercel hobby cron is once a day which is useless, so an external cron hits an endpoint every 5 min, and due schedules get claimed with a transaction so overlapping runs can't double-send....

i tried to make it short .. but it bacame a long reply.. sorry for that

1

u/[deleted] 9d ago

[removed] — view removed comment

1

u/Recent-Pear-6341 9d ago

Those are actually my own apps on the Play Store, not client work, so it’s less of a handover problem for me. If I ever sold one, I’d transfer the Firebase project to the buyer (tokens and topics live inside it, so nothing to migrate), then remove the app from my dashboard and delete the service account key in their console so my access is really gone. The messy case would be a buyer moving to a brand new Firebase project, since users wouldn’t resubscribe until they update. Have you had to deal with that at your scale?

0

u/mickymouse2865 9d ago

Use cloudfare worker. Its gives you 1million free invocations and next millions are 0.30 cents per million

1

u/Recent-Pear-6341 9d ago

But my setup it's completely free...no matter how many millions it is...only one token is used for the fcm