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)

apis:
  - apiName: eventarc.googleapis.com
    reason: Powers all events and triggers
  - apiName: run.googleapis.com
    reason: Powers 2nd-gen functions

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)

apis:
  - apiName: eventarc.googleapis.com
    reason: Powers all events and triggers
  - apiName: run.googleapis.com
    reason: Powers 2nd-gen functions

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)

apis:
  - apiName: eventarc.googleapis.com
    reason: Powers all events and triggers
  - apiName: run.googleapis.com
    reason: Powers 2nd-gen functions

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)

apis:
  - apiName: eventarc.googleapis.com
    reason: Powers all events and triggers
  - apiName: run.googleapis.com
    reason: Powers 2nd-gen functions

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}