Write Cloud Functions for an extension

When you create an extension, you write its logic using Cloud Functions, in much the same way as you would write a function that would only ever be used in your own project. You declare your functions in the extension.yaml file, and when users install your extension, these functions get deployed into their project.

See the Cloud Functions documentation for general information on using Cloud Functions.

1st and 2nd generation Cloud Functions

Firebase supports both 1st-generation and 2nd-generation Cloud Functions. However, Firebase Extensions currently have some restrictions on which generation of cloud function you can use with certain trigger types. For this reason, many extensions include a mix of 1st and 2nd generation functions.

Function generation support is noted for each trigger type, below.

Special considerations

  • Some function definitions require you to specify information that is also specified in the extension.yaml file. For example, Cloud Firestore has a document() method that specifies the document pattern to watch, and its corresponding declaration in extension.yaml has a resource field that specifies the same.

    In these situations, the configuration specified in the extension.yaml file is used and the configuration specified in the function definition is ignored.

    It is common practice to specify the configured value in the function definition regardless, for the sake of documentation. The examples on this page follow this pattern.

  • The Cloud Functions 1st gen SDK has a functions.config() method and functions:config:set CLI command that you can use to work with parameterized values in 1st gen functions. This technique is deprecated in Cloud Functions and will not work at all in an extension. Instead, use the functions.params module (recommended) or process.env.

Using TypeScript

Most of the documentation for developing your own extension describes workflows using JavaScript for Cloud Functions for Firebase. However, you can instead write your functions using TypeScript.

In fact, all the official Firebase extensions are written in TypeScript. You can review those extensions for some best practices to use TypeScript for your extension.

If you do write your extension's functions in TypeScript, you must do the following before installing your extension:

  1. Compile your extension's functions source code to JavaScript.

    The firebase ext:dev:init command allows you to choose TypeScript for writing your functions. The command provides you with a complete, installable extension as well as a build script that you can run with npm run build.

  2. In your package.json file, make sure to point the main field at the generated JavaScript.

  3. If you're installing or uploading your extension from local source, compile your TypeScript files first.

Supported function triggers

HTTP triggers

An HTTP-triggered function is deployed to a public https endpoint and runs when the endpoint is accessed.

See Call functions via HTTP requests in the Cloud Functions documentation for information on writing HTTP-triggered functions.

Function definition (1st-gen only)

import { https } from "firebase-functions/v1"; export const yourFunctionName = https.onRequest(async (req, resp) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  runtime: nodejs16  httpsTrigger: {}  - name: anotherFunction  type: ... 

Callable functions

Callable functions are similar to HTTP-triggered functions, but they implement a protocol that makes them convenient to call from your client-side code.

See Call functions from your app in the Cloud Functions documentation for information on using callable functions.

Function definition (1st-gen only)

import { https } from "firebase-functions/v1"; export const yourFunctionName = https.onCall(async (data, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  runtime: nodejs16  httpsTrigger: {}  - name: anotherFunction  type: ... 

Scheduled function triggers

A scheduled function runs repeatedly based on a customizable schedule.

See Schedule functions in the Cloud Functions documentation for information on writing scheduled functions.

Function definition (1st-gen only)

import { pubsub } from "firebase-functions/v1"; export const yourFunctionName = pubsub.schedule("every 6 hours").onRun((context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  scheduleTrigger:  schedule: 'every 5 minutes'  - name: anotherFunction  type: ... 

Here are the available subfields for scheduleTrigger:

Field Description
schedule
(required)

The frequency at which you want the function to run.

This field can accept strings that use either syntax (wrapping in single-quotes is required):

timeZone
(optional)

The time zone in which the schedule will run.

If you want users to be able to configure the schedule when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  scheduleTrigger:  schedule: ${SCHEDULE_FREQUENCY}  - name: anotherFunction  type: ... params:  - param: SCHEDULE_FREQUENCY  label: Schedule  description: How often do you want to run yourFunctionName()?  type: string  default: 'every 5 minutes' # Specifying a default is optional.  required: true 

Task queue triggers

A task queue function is triggered either on your extension's lifecycle events or when manually added to your extension's task queue using the Admin SDK's TaskQueue.enqueue() method.

See Handle your extension's lifecycle events for information on writing functions that handle lifecycle events.

See Enqueue functions with Cloud Tasks in the Cloud Functions documentation for information on writing task queue functions.

Function definition (1st-gen only)

import { tasks } from "firebase-functions/v1"; export const yourFunctionName = tasks.taskQueue().onDispatch(async (data, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: myTaskFunction  type: firebaseextensions.v1beta.function  description: >-  Perform a task when triggered by a lifecycle event  properties:  taskQueueTrigger: {} 

Set the taskQueueTrigger property set to either {} or a map of options which tune the rate limits and retry behavior of the task queue (see Tuning the task queue).

If you want to trigger your function on your extension's lifecycle events, add lifecycleEvents records with the name of the function and an optional processing message, which will be displayed in the Firebase console when processing begins.

lifecycleEvents:  onInstall:  function: myTaskFunction  processingMessage: Resizing your existing images  onUpdate:  function: myOtherTaskFunction  processingMessage: Setting up your extension  onConfigure:  function: myOtherTaskFunction  processingMessage: Setting up your extension 

Analytics

An Analytics-triggered function runs when a specified Analytics event gets logged.

See Google Analytics triggers in the Cloud Functions documentation for information on writing Analytics-triggered functions.

Function definition (1st-gen only)

import { analytics } from "firebase-functions/v1"; export const yourFunctionName = analytics.event("event_name").onLog((event, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/google.firebase.analytics/eventTypes/event.log  resource: projects/${PROJECT_ID}/events/ga_event  - name: anotherFunction  type: ... 

If you want users to be able to configure the Analytics event to listen for when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/google.firebase.analytics/eventTypes/event.log  resource: projects/${PROJECT_ID}/events/${EVENT_NAME}  - name: anotherFunction  type: ... params:  - param: EVENT_NAME  label: Analytics event  description: What event do you want to respond to?  type: string  default: ga_event # Specifying a default is optional.  required: true 

Authentication

An authentication-triggered function runs when a user is created or deleted.

See Firebase Authentication triggers in the Cloud Functions documentation for information on writing auth-triggered functions.

Function definition (1st-gen only)

import { auth } from "firebase-functions/v1"; export const yourFunctionName = auth.user().onCreate((user, context) => {  // ... }); export const yourFunctionName2 = auth.user().onDelete((user, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/firebase.auth/eventTypes/user.create  resource: projects/${PROJECT_ID}  - name: anotherFunction  type: ... 

The following table shows how to specify each of the supported Authentication event types:

Cloud Functions event trigger eventType Description
onCreate() providers/firebase.auth/eventTypes/user.create New user created
onDelete() providers/firebase.auth/eventTypes/user.delete User deleted

Cloud Firestore

A Cloud Firestore-triggered function runs when a document is created, updated, or deleted.

See Cloud Firestore triggers in the Cloud Functions documentation for information on writing Firestore-triggered functions.

Function definition (1st-gen only)

import { firestore } from "firebase-functions/v1"; export const yourFunctionName = firestore.document("collection/{doc_id}")  .onCreate((snapshot, context) => {  // ...  }); export const yourFunctionName2 = firestore.document("collection/{doc_id}")  .onUpdate((change, context) => {  // ...  }); export const yourFunctionName3 = firestore.document("collection/{doc_id}")  .onDelete((snapshot, context) => {  // ...  }); export const yourFunctionName4 = firestore.document("collection/{doc_id}")  .onWrite((change, context) => {  // onWrite triggers on creation, update, and deletion.  // ...  }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/cloud.firestore/eventTypes/document.write  resource: projects/${PROJECT_ID}/databases/(default)/documents/collection/{documentID}  - name: anotherFunction  type: ... 

The following table shows how to specify each of the supported Cloud Firestore event types:

Cloud Functions event trigger eventType Description
onCreate() providers/cloud.firestore/eventTypes/document.create New document created
onDelete() providers/cloud.firestore/eventTypes/document.delete Document deleted
onUpdate() providers/cloud.firestore/eventTypes/document.update Document updated
onWrite() providers/cloud.firestore/eventTypes/document.write Document created, deleted, or updated

If you want users to be able to configure the document path when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/cloud.firestore/eventTypes/document.write  resource: projects/${PROJECT_ID}/databases/(default)/documents/${YOUR_DOCUMENT_PATH}  - name: anotherFunction  type: ... params:  - param: YOUR_DOCUMENT_PATH  label: Cloud Firestore path  description: Where do you want to watch for changes?  type: string  default: path/to/{documentID} # Specifying a default is optional.  required: true 

Pub/Sub

A Pub/Sub-triggered function runs when a message is published to a specific topic.

See Pub/Sub triggers in the Cloud Functions documentation for information on writing Pub/Sub-triggered functions.

Function definition (1st-gen only)

import { pubsub } from "firebase-functions/v1"; export const yourFunctionName = pubsub.topic("topic_name").onPublish((message, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.pubsub.topic.publish  resource: projects/${PROJECT_ID}/topics/topic-name  - name: anotherFunction  type: ... 

If you want users to be able to configure the Pub/Sub topic when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.pubsub.topic.publish  resource: projects/${PROJECT_ID}/topics/${PUBSUB_TOPIC}  - name: anotherFunction  type: ... params:  - param: PUBSUB_TOPIC  label: Pub/Sub topic  description: Which Pub/Sub topic do you want to watch for messages?  type: string  default: topic-name # Specifying a default is optional.  required: true 

Realtime Database

A Realtime Database-triggered function runs when a path that matches a specified pattern is created, updated, or deleted.

See Realtime Database triggers in the Cloud Functions documentation for information on writing RTDB-triggered functions.

Function definition (1st-gen only)

import { database } from "firebase-functions/v1"; export const yourFunctionName = database.ref("path/to/{item}")  .onCreate((snapshot, context) => {  // ...  }); export const yourFunctionName2 = database.ref("path/to/{item}")  .onUpdate((change, context) => {  // ...  }); export const yourFunctionName3 = database.ref("path/to/{item}")  .onDelete((snapshot, context) => {  // ...  }); export const yourFunctionName4 = database.ref("path/to/{item}")  .onWrite((change, context) => {  // onWrite triggers on creation, update, and deletion.  // ...  }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/google.firebase.database/eventTypes/ref.create  # DATABASE_INSTANCE (project's default instance) is an auto-populated  # parameter value. You can also specify an instance.  resource: projects/_/instances/${DATABASE_INSTANCE}/refs/path/to/{itemId}  - name: anotherFunction  type: ... 

The following table shows how to specify each of the supported Cloud Firestore event types:

Cloud Functions event trigger eventType Description
onCreate() providers/google.firebase.database/eventTypes/ref.create Data created
onDelete() providers/google.firebase.database/eventTypes/ref.delete Data deleted
onUpdate() providers/google.firebase.database/eventTypes/ref.update Data updated
onWrite() providers/google.firebase.database/eventTypes/ref.write Data created, deleted, or updated

If you want users to be able to configure the path to watch when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: providers/google.firebase.database/eventTypes/ref.create  # DATABASE_INSTANCE (project's default instance) is an auto-populated  # parameter value. You can also specify an instance.  resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${DB_PATH}  - name: anotherFunction  type: ... params:  - param: DB_PATH  label: Realtime Database path  description: Where do you want to watch for changes?  type: string  default: path/to/{itemId} # Specifying a default is optional.  required: true 

Remote Config

A Remote Config-triggered function runs when a project's parameter template is updated.

See Remote Config triggers in the Cloud Functions documentation for information on writing Remote Config-triggered functions.

Function definition (1st-gen only)

import { remoteConfig } from "firebase-functions/v1"; export const yourFunctionName = remoteConfig.onUpdate((version, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.firebase.remoteconfig.update  resource: projects/${PROJECT_ID}  - name: anotherFunction  type: ... 

Cloud Storage

A Cloud Storage-triggered function runs when an object is created, archived, or deleted, or when its metadata changes.

See Cloud Storage triggers in the Cloud Functions documentation for information on writing Storage-triggered functions.

Function definition (1st-gen only)

import { storage } from "firebase-functions/v1"; export const yourFunctionName = storage.object().onFinalize((object, context) => {  // ... }); export const yourFunctionName2 = storage.object().onMetadataUpdate((object, context) => {  // ... }); export const yourFunctionName3 = storage.object().onArchive((object, context) => {  // ... }); export const yourFunctionName4 = storage.object().onDelete((object, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.storage.object.finalize  # STORAGE_BUCKET (project's default bucket) is an auto-populated  # parameter. You can also specify a bucket.  resource: projects/_/buckets/${STORAGE_BUCKET}  - name: anotherFunction  type: ... 

The following table shows how to specify each of the supported Cloud Storage event types:

Cloud Functions event trigger eventType Description
onFinalize() google.storage.object.finalize Object created
onMetadataUpdate() google.storage.object.metadataUpdate Object metadata updated
onArchive() google.storage.object.archive Object was archived
onDelete() google.storage.object.delete Object deleted

If you want users to be able to configure the storage bucket when they install your extension, add a new parameter to your extension.yaml file and reference the parameter in your function's resource declaration:

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.storage.object.finalize  resource: projects/_/buckets/${YOUR_BUCKET}  - name: anotherFunction  type: ... params:  - param: YOUR_BUCKET  label: Cloud Storage bucket  description: Which bucket do you want to watch for changes?  type: selectResource  resourceType: storage.googleapis.com/Bucket  default: ${STORAGE_BUCKET} # Specifying a default is optional.  required: true 

Test Lab

A Test Lab-triggered function runs when a test matrix finishes its tests.

See Firebase Test Lab triggers in the Cloud Functions documentation for information on writing Test Lab-triggered functions.

Function definition (1st-gen only)

import { testLab } from "firebase-functions/v1"; export const yourFunctionName = testLab.testMatrix().onComplete((matrix, context) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourFunctionName  type: firebaseextensions.v1beta.function  properties:  eventTrigger:  eventType: google.testing.testMatrix.complete  resource: projects/${PROJECT_ID}/testMatrices/{matrixId}  - name: anotherFunction  type: ... 

Crashlytics alert triggers

A Crashlytics-triggered function runs when Crashlytics publishes an alert.

See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.

Function definition (2nd-gen only)

import {  onNewFatalIssuePublished,  onNewNonfatalIssuePublished,  onNewAnrIssuePublished,  onRegressionAlertPublished,  onVelocityAlertPublished,  onStabilityDigestPublished, } from "firebase-functions/v2/alerts/crashlytics"; export const yourFunctionName = onNewFatalIssuePublished((event) => {  // ... }); export const yourFunctionName2 = onNewNonfatalIssuePublished((event) => {  // ... }); export const yourFunctionName3 = onNewAnrIssuePublished((event) => {  // ... }); export const yourFunctionName4 = onRegressionAlertPublished((event) => {  // ... }); export const yourFunctionName5 = onVelocityAlertPublished((event) => {  // ... }); export const yourFunctionName6 = onStabilityDigestPublished((event) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourfunctionname  type: firebaseextensions.v1beta.v2function  properties:  buildConfig:  runtime: nodejs16  serviceConfig:  availableMemory: 512M  eventTrigger:  eventType: google.firebase.firebasealerts.alerts.v1.published  triggerRegion: global  eventFilters:  - attribute: alerttype  value: crashlytics.newFatalIssue  - name: anotherFunction  type: ... 

You can use the following values for alerttype

  • crashlytics.newFatalIssue
  • crashlytics.newNonfatalIssue
  • crashlytics.regression
  • crashlytics.stabilityDigest
  • crashlytics.velocity
  • crashlytics.newAnrIssue

Performance Monitoring alert triggers

A Performance Monitoring-triggered function runs when Performance Monitoring publishes an alert.

See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.

Function definition (2nd-gen only)

import { onThresholdAlertPublished } from "firebase-functions/v2/alerts/performance"; export const yourFunctionName = onThresholdAlertPublished((event) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourfunctionname  type: firebaseextensions.v1beta.v2function  properties:  buildConfig:  runtime: nodejs16  serviceConfig:  availableMemory: 512M  eventTrigger:  eventType: google.firebase.firebasealerts.alerts.v1.published  triggerRegion: global  eventFilters:  - attribute: alerttype  value: performance.threshold  - name: anotherFunction  type: ... 

App Distribution alert triggers

A App Distribution-triggered function runs when App Distribution publishes an alert.

See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.

Function definition (2nd-gen only)

import {  onNewTesterIosDevicePublished,  onInAppFeedbackPublished } from "firebase-functions/v2/alerts/appDistribution"; export const yourFunctionName = onNewTesterIosDevicePublished((event) => {  // ... }); export const yourFunctionName2 = onInAppFeedbackPublished((event) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourfunctionname  type: firebaseextensions.v1beta.v2function  properties:  buildConfig:  runtime: nodejs16  serviceConfig:  availableMemory: 512M  eventTrigger:  eventType: google.firebase.firebasealerts.alerts.v1.published  triggerRegion: global  eventFilters:  - attribute: alerttype  value: appDistribution.inAppFeedback  - name: anotherFunction  type: ... 

You can use the following values for alerttype

  • appDistribution.newTesterIosDevice
  • appDistribution.inAppFeedback

Custom event triggers (Eventarc)

An Eventarc-triggered function runs when a specific event type is published to a specific channel.

See Create and handle custom event triggers in the Cloud Functions documentation for information on writing Eventarc-triggered functions.

You can also publish events from your extensions to give users a way to insert custom logic into your extension. See Use developer-provided custom logic in an extension.

Function definition (2nd-gen only)

import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; export const yourFunctionName = onCustomEventPublished((event) => {  // ... }); 

Resource declaration (extension.yaml)

resources:  - name: yourfunctionname  type: firebaseextensions.v1beta.v2function  properties:  # LOCATION is a user-configured parameter value specified by the user  # during installation.  location: ${param:LOCATION}  buildConfig:  runtime: nodejs16  serviceConfig:  availableMemory: 512M  timeoutSeconds: 60  eventTrigger:  eventType: firebase.extensions.storage-resize-images.v1.complete  channel: projects/${param:PROJECT_ID}/locations/us-central1/channels/firebase  - name: anotherFunction  type: ... 

The channel must already exist when your extension is installed. For example, if you depend on custom events from another extension that creates the channel, instruct your users to install that extension first.

The above example would create a custom event trigger for the "default" Firebase channel in us-central1 region. You can make the channel name and region customizable by using parameters. For example:

 params:  - param: EVENTARC_CHANNEL_NAME  label: Eventarc channel name  description: What is the name of the Eventarc channel.  default: firebase  type: string  required: true resources:  - name: yourfunctionname  type: firebaseextensions.v1beta.v2function  properties:  location: ${param:LOCATION}  eventTrigger:  eventType: firebase.extensions.storage-resize-images.v1.complete  channel: projects/${param:PROJECT_ID}/locations/${param:LOCATION}/channels/${param:EVENTARC_CHANNEL_NAME}