Extend with Cloud Run functions (2nd gen)
With Cloud Run functions, you can deploy code to handle events triggered by changes in your Firestore database. This allows you to add server-side functionality without running your own servers.
Extend Firestore with Cloud Run functions (2nd gen)
Cloud Run functions (2nd gen) supports the following Firestore event triggers to let you create handlers tied to Firestore events:
Event Type | Trigger |
---|---|
google.cloud.firestore.document.v1.created |
Triggered when a document is written to for the first time. |
google.cloud.firestore.document.v1.updated |
Triggered when a document already exists and has any value changed. |
google.cloud.firestore.document.v1.deleted |
Triggered when a document is deleted. |
google.cloud.firestore.document.v1.written |
Triggered when created , updated or deleted is triggered. |
google.cloud.firestore.document.v1.created.withAuthContext |
Same as created but adds authentication information. |
google.cloud.firestore.document.v1.updated.withAuthContext |
Same as updated but adds authentication information. |
google.cloud.firestore.document.v1.deleted.withAuthContext |
Same as deleted but adds authentication information. |
google.cloud.firestore.document.v1.written.withAuthContext |
Same as written but adds authentication information. |
Firestore events trigger only on document changes. An update to a Firestore document where data is unchanged (a no-op write) does not generate an update or write event. It is not possible to add events to specific fields.
Include authentication context in the event
To include additional authentication information about the event, use an event
trigger with the withAuthContext
extension. This extension adds additional
information about the principal that triggered the event. It adds the
authtype
and authid
attributes in addition to the information returned in
the base event. See the
authcontext
reference for more information about attribute values.
Write a Firestore-triggered function
To write a function that responds to Firestore events, prepare to specify following during deployment:
- a trigger event type
- a trigger event filter to select the documents associated with the function
- the function code to run
Trigger event filters
When you specify an event filter, you can specify either an exact document
match or a path pattern. Use a path pattern to match multiple documents with
wildcards, *
or **
.
For example, you can respond to changes to the following document:
users/marie
Use wildcards, *
or **
, to respond to changes in documents
that match a pattern. A wildcard *
matches a single segment and
the a multi-segment wildcard **
matches zero or more segments in the pattern.
For single segment matches (*
) you can also use a named capture group. For
example, users/{userId}
.
For example:
Pattern | Description |
---|---|
/users/* or /users/{userId} |
Matches all documents in the /users collection. Does not match documents in sub-collections like /users/marie/messages/33e2IxYBD9enzS50SJ68 |
/users/** |
Matches all documents in the /users collection and documents in subcollections like /users/marie/messages/33e2IxYBD9enzS50SJ68 |
To learn more about path patterns, see Eventarc path patterns.
Your trigger must always point to a document, even if you're using a wildcard.
For example, users/{userId=*}/{messageCollectionId=*}
is not valid because {messageCollectionId=*}
is a collection. However, users/{userId=*}/{messageCollectionId}/{messageId=*}
is
valid because {messageId=*}
will always point to a document.
Example functions
The following sample demonstrates how to receive Firestore events.
To work with the document data involved in an event, look at the value
and
old_value
fields.
value
: ADocument
object that contains a post-operation document snapshot. This field is not populated for delete events.old_value
: ADocument
object that contains a pre-operation document snapshot. This field is only populated for update and delete events.
Go
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Use protobufjs to decode the event data. Include thegoogle.events.cloud.firestore.v1
data.proto
in your source.
Python
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
C#
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
The following examples converts strings added to the original
field of an
affected doc to uppercase and writes the new value to the same document:
Go
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Use protobufjs to decode the event data. Include thegoogle.events.cloud.firestore.v1
data.proto
in your source.
Python
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
C#
To authenticate to Firestore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Include the proto dependencies in your source
You must include the Firestore data.proto
file in the source directory for your function. This file imports the following
protos which you must also include in your source directory:
Use the same directory structure for the dependencies. For example, place
struct.proto
within google/protobuf
.
These files are required to decode event data. If your function source does not include these files, it returns an error when it runs.
Event attributes
Each event includes data attributes that include information about the event such as the time the event triggered. Firestore adds additional data about the database and document involved in the event. You can access these attributes as follows:
Java
logger.info("Function triggered by event on: " + event.getSource()); logger.info("Event type: " + event.getType()); logger.info("Event time " + event.getTime()); logger.info("Event project: " + event.getExtension("project")); logger.info("Event location: " + event.getExtension("location")); logger.info("Database name: " + event.getExtension("database")); logger.info("Database document: " + event.getExtension("document")); // For withAuthContext events logger.info("Auth information: " + event.getExtension("authid")); logger.info("Auth information: " + event.getExtension("authtype"));
Node.js
console.log(`Function triggered by event on: ${cloudEvent.source}`); console.log(`Event type: ${cloudEvent.type}`); console.log(`Event time: ${cloudEvent.time}`); console.log(`Event project: ${cloudEvent.project}`); console.log(`Event location: ${cloudEvent.location}`); console.log(`Database name: ${cloudEvent.database}`); console.log(`Document name: ${cloudEvent.document}`); // For withAuthContext events console.log(`Auth information: ${cloudEvent.authid}`); console.log(`Auth information: ${cloudEvent.authtype}`);
Python
print(f"Function triggered by change to: {cloud_event['source']}") print(f"Event type: {cloud_event['type']}") print(f"Event time: {cloud_event['time']}") print(f"Event project: {cloud_event['project']}") print(f"Location: {cloud_event['location']}") print(f"Database name: {cloud_event['database']}") print(f"Document: {cloud_event['document']}") // For withAuthContext events print(f"Auth information: {cloud_event['authid']}") print(f"Auth information: {cloud_event['authtype']}")
Deploy a function
Users deploying Cloud Run functions must have the Cloud Run functions Developer IAM role or a role that includes the same permissions. See also Additional configuration for deployment.
You can deploy a function using either the gcloud CLI or the Google Cloud console. The example below demonstrates deployment with the gcloud CLI. For details on deployment with the Google Cloud console, see Deploy Cloud Run functions
gcloud
-
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
Use the
gcloud functions deploy
command to deploy a function:gcloud functions deploy YOUR_FUNCTION_NAME \ --gen2 \ --region=FUNCTION_LOCATION \ --trigger-location=TRIGGER_LOCATION \ --runtime=YOUR_RUNTIME \ --source=YOUR_SOURCE_LOCATION \ --entry-point=YOUR_CODE_ENTRYPOINT \ --trigger-event-filters="type=EVENT_FILTER_TYPE" \ --trigger-event-filters="database=DATABASE" \ --trigger-event-filters-path-pattern="document=DOCUMENT" \
The first argument,
YOUR_FUNCTION_NAME
, is a name for your deployed function. The function name must start with a letter followed by up to 62 letters, numbers, hyphens, or underscores, and must end with a letter or a number.The
--gen2
flag specifies that you want to deploy to Cloud Run functions (2nd gen). Omitting this flag results in deployment to Cloud Run functions (1st gen).The
--region
flag specifies the region in which to deploy your function.To maximize proximity, set to a region near your Firestore database. If your Firestore database is in a multi-region location, set to
us-central1
for databases innam5
and toeurope-west4
for databases ineur3
. For regional Firestore locations, set to the same region.The
--trigger-location
flag specifies the location of the trigger. You must set this flag to the location of your Firestore database.The
--runtime
flag specifies which language runtime your function uses. Cloud Run functions supports several runtimes - see Runtimes for more information.The
--source
flag specifies the location of your function source code. See the following for details:The
--entry-point
flag specifies the entry point to your function in your source code. This is the code that will be executed when your function runs. The value of this flag must be a function name or fully-qualified class name that exists in your source code. See Function entry point for more information.EVENT_FILTER_TYPE
: Firestore supports the following event types.google.cloud.firestore.document.v1.created
: event is sent when a document is written to for the first time.google.cloud.firestore.document.v1.updated
: event is sent when a document already exists and has any value changed.google.cloud.firestore.document.v1.deleted
: event is sent when a document is deleted.google.cloud.firestore.document.v1.written
: event is sent when a document is created, updated, or deleted.google.cloud.firestore.document.v1.created.withAuthContext
: event is sent when a document is written to for the first time and the event includes additional authentication informationgoogle.cloud.firestore.document.v1.updated.withAuthContext
: event is sent when a document already exists and has any value changed. Includes additional authentication informationgoogle.cloud.firestore.document.v1.deleted.withAuthContext
: event is sent when a document is deleted. Includes additional authentication informationgoogle.cloud.firestore.document.v1.written.withAuthContext
: event is sent when a document is created, updated, or deleted and event. Includes additional authentication information
DATABASE
: the Firestore database. For the default database name, use(default)
.DOCUMENT
: the database path that triggers events when data is created, updated, or deleted. The operator can be one of the following:- Equal; for example,
--trigger-event-filters=document='users/marie'
- Path pattern; for example,
--trigger-event-filters-path-pattern=document='users/*'
. For more information, see Understand path patterns.
- Equal; for example,
You can optionally specify additional configuration, networking, and security options when you deploy a function.
For a complete reference on the deployment command and its flags, see the
gcloud functions deploy
documentation.
Example deployments
The following examples demonstrate deployments with the Google Cloud CLI.
Deploy a function for a database in the us-west2
region:
gcloud functions deploy gcfv2-trigger-firestore-node \
--gen2 \
--region=us-west2 \
--trigger-location=us-west2 \
--runtime=nodejs18 \
--source=gs://CLOUD_STORAGE_BUCKET/firestoreEventFunction.zip \
--entry-point=makeUpperCase \
--trigger-event-filters=type=google.cloud.firestore.document.v1.written \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern=document='messages/{pushId}'
Deploy a function for a database in the nam5
multi-region:
gcloud functions deploy gcfv2-trigger-firestore-python \
--gen2 \
--region=us-central1 \
--trigger-location=nam5 \
--runtime=python311 \
--source=gs://CLOUD_STORAGE_BUCKET/firestoreEventFunction.zip \
--entry-point=make_upper_case \
--trigger-event-filters=type=google.cloud.firestore.document.v1.written.withAuthContext \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern=document='messages/{pushId}'
Limitations
Note the following limitations for Firestore triggers for Cloud Run functions:
- Cloud Run functions (1st gen) prerequisites an existing "(default)" database in Firestore native mode. It does not support Firestore named databases or Datastore mode. Please use Cloud Run functions (2nd gen) to configure events in such cases.
- Ordering is not guaranteed. Rapid changes can trigger function invocations in an unexpected order.
- Events are delivered at least once, but a single event may result in multiple function invocations. Avoid depending on exactly-once mechanics, and write idempotent functions.
- Firestore in Datastore mode requires Cloud Run functions (2nd gen). Cloud Run functions (1st gen) does not support Datastore mode.
- A trigger is associated with a single database. You cannot create a trigger that matches multiple databases.
- Deleting a database does not automatically delete any triggers for that database. The trigger stops delivering events but continues to exist until you delete the trigger.
- If a matched event exceeds the maximum request size, the
event might not be delivered to Cloud Run functions (1st gen).
- Events not delivered because of request size are logged in platform logs and count towards the log usage for the project.
- You can find these logs in the Logs Explorer with the message "Event cannot deliver to
Cloud function due to size exceeding the limit for 1st gen..." of
error
severity. You can find the function name under thefunctionName
field. If thereceiveTimestamp
field is still within an hour from now, you can infer the actual event content by reading the document in question with a snapshot before and after the timestamp. - To avoid such cadence, you can:
- Migrate and upgrade to Cloud Run functions (2nd gen)
- Downsize the document
- Delete the Cloud Run functions in question
- You can turn off the logging itself using exclusions but note that the offending events will still not be delivered.
Eventarc and Firestore locations
Eventarc does not support multi-regions for Firestore event triggers, but you can still create triggers for Firestore databases in multi-region locations. Eventarc maps Firestore multi-region locations to the following Eventarc regions:
Firestore multi-region | Eventarc region |
---|---|
nam5 |
us-central1 |
eur3 |
europe-west4 |
Differences between Cloud Run functions 2nd gen and 1st gen
Cloud Run functions (2nd gen) uses Eventarc events for all runtimes. Previously, Cloud Run functions (1st gen) used Eventarc events for only some runtimes. Eventarc events introduce the following differences from Cloud Run functions (1st gen).
The Firestore triggers for Eventarc support additional destinations besides Cloud Run functions. You can route
CloudEvents
to a number of destinations including, but not limited to Cloud Run, GKE, and Workflows.Firestore triggers for Eventarc retrieve the trigger definition at the start of a database write operation and uses that definition to decide if Firestore should emit an event. The write operation does not take into account any changes to trigger definition that might happen as it runs.
Cloud Run functions (1st gen) retrieves the trigger definition during the evaluation of the database write, and changes to the trigger during evaluation can affect if Firestore emits an event or not.
For more details, see Cloud Run functions version comparison.