Skip to main content
A document lands in Firestore and someone should know. This guide sends a push, and an email instead when the push cannot land.

What you will build

Prerequisites

  • , with FCM connected and device tokens syncing
  • A published with push and email content

What this adds over calling FCM yourself

You already have Firebase, so calling FCM from the same function is one line shorter. It is worth being precise about what the extra hop buys, because “use a platform” is not an argument. You address a person, not a device. FCM needs a registration token. Courier needs a user_id, and resolves the tokens itself, including the case where someone has three devices and one stale token. A failed push becomes an email. FCM can tell you a token was rejected. It cannot then reach the person another way. One routing line does. Preferences apply without a conditional. If the recipient muted this notification type, Courier filters it. With raw FCM that check is code you write and maintain at every call site. One log covers both channels. A push that failed and an email that succeeded are the same message in , not two systems to correlate. If none of those matter for a given notification, call FCM directly. They usually start mattering around the second channel.

Set it up

1

Install and store the key

In your functions directory:
2

Write the trigger

This is a 2nd-gen Firestore trigger. The path carries a wildcard, and its value arrives on event.params.
functions/index.js
Two lines are doing the work worth noticing.routing: { method: "single", channels: ["push", "email"] } walks the list and stops at the first channel that works. Push first, email as its failover. Swap to all and both go out every time.if (!snapshot) return guards the case where the document is gone by the time the function runs. Firestore triggers are not transactional with the write.
3

Deploy

Verify

1

Write a document

Add a comment document under a path matching the trigger, from your app or the Firebase console.
2

Check the function ran

3

Confirm which channel delivered

Open . The timeline names the channel that delivered. To prove the fallback, remove the user’s device tokens and write again. The same send should arrive by email.

Adapt it for other writes

The update case is the one to be careful with. A trigger on every write fires on fields nobody cares about, so compare before and after and return early. That is the difference between a useful alert and a reason to mute your app. For fan-out, when many people are watching the document rather than one, address a list instead of a user. covers that shape.