Extend Realtime Database with Cloud Functions

Note: This feature is a public preview. This means that the functionality might change in backward-incompatible ways. A preview release is not subject to any SLA or deprecation policy and may receive limited or no support.

WithCloud Functions, you can handle events in theFirebase Realtime Database with no need to update client code.Cloud Functions lets you runRealtime Database operations with full administrativeprivileges, and ensures that each change toRealtime Database is processedindividually. You can makeFirebase Realtime Database changes via the data snapshotor via the Admin SDK.

In a typical lifecycle, aFirebase Realtime Database function does the following:

  1. Waits for changes to a particularRealtime Database path.
  2. Triggers when an event occurs and performs its tasks.
  3. Receives a data object that contains a snapshot of the data storedat that path.

You can trigger a function in response to the writing, creating, updating, ordeleting of database nodes inFirebase Realtime Database. Tocontrol when the function triggers, specify one of the event handlers, andspecify theRealtime Database path where it will listen for events.

Setting the function location

Distance between the location of aRealtime Database instance and the location of thefunction can create significant network latency. Also, a mismatch betweenregions can result in deployment failure. To avoid these situations, specifythefunction location sothat it matches thedatabase instance location.

HandlingRealtime Database events

Functions let you handleRealtime Database events at two levels of specificity;you can listen for specifically for only write, creation, update,or deletion events, or you can listen for any change of any kind to a reference.

These handlers for responding toRealtime Database events are available:

Node.js

  • onValueWritten() Triggered when data is created, updated, or deleted inRealtime Database.
  • onValueCreated() Only triggered when data is created inRealtime Database.
  • onValueUpdated() Only triggered when data is updated inRealtime Database.
  • onValueDeleted() Only triggered when data is deleted inRealtime Database.

Python

  • on_value_written() Triggered when data is created, updated, or deleted inRealtime Database.
  • on_value_created() Only triggered when data is created inRealtime Database.
  • on_value_updated() Only triggered when data is updated inRealtime Database.
  • on_value_deleted() Only triggered when data is deleted inRealtime Database.

Import required modules

In your function source, you must import SDK modules that you want to use. Forthis sample, it is necessary to import HTTP andRealtime Database modules along withtheFirebase Admin SDK module for writing toRealtime Database.

Node.js

// The Cloud Functions for Firebase SDK to setup triggers and logging.const{onRequest}=require("firebase-functions/https");const{onValueCreated}=require("firebase-functions/database");const{logger}=require("firebase-functions");// The Firebase Admin SDK to access the Firebase Realtime Database.constadmin=require("firebase-admin");admin.initializeApp();

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.fromfirebase_functionsimportdb_fn,https_fn# The Firebase Admin SDK to access the Firebase Realtime Database.fromfirebase_adminimportinitialize_app,dbapp=initialize_app()

Specify instance and path

To control when and where your function should trigger, configure your functionwith a path and optionally aRealtime Database instance. If you do notspecify an instance, the function listens to the allRealtime Database instancesin the function region. You may also specify aRealtime Database instance patternto deploy to a selective subset of instances in the same region.

For example:

Node.js

// AllRealtime Database instances in default function region us-central1 at path "/user/{uid}"// There must be at least oneRealtime Database present in us-central1.constonWrittenFunctionDefault=onValueWritten("/user/{uid}",(event)=>{// …});// Instance named "my-app-db-2", at path "/user/{uid}".// The "my-app-db-2" instance must exist in this region.constOnWrittenFunctionInstance=onValueWritten({ref:"/user/{uid}",instance:"my-app-db-2"// This example assumes us-central1, but to set location:// region: "europe-west1"},(event)=>{// …});// Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com.// There must be at least oneRealtime Database with "my-app-db-*" prefix in this region.constonWrittenFunctionInstance=onValueWritten({ref:"/user/{uid=*@gmail.com}",instance:"my-app-db-*"// This example assumes us-central1, but to set location:// region: "europe-west1"},(event)=>{// …});

Python

# All Realtime Database instances in default function region us-central1 at path "/user/{uid}"# There must be at least one Realtime Database present in us-central1.@db_fn.on_value_written(r"/user/{uid}")defonwrittenfunctiondefault(event:db_fn.Event[db_fn.Change]):# ...pass# Instance named "my-app-db-2", at path "/user/{uid}".# The "my-app-db-2" instance must exist in this region.@db_fn.on_value_written(reference=r"/user/{uid}",instance="my-app-db-2",# This example assumes us-central1, but to set location:# region="europe-west1",)defon_written_function_instance(event:db_fn.Event[db_fn.Change]):# ...pass# Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com.# There must be at least one Realtime Database with "my-app-db-*" prefix in this region.@db_fn.on_value_written(reference=r"/user/{uid=*@gmail.com}",instance="my-app-db-*",# This example assumes us-central1, but to set location:# region="europe-west1",)defon_written_function_instance(event:db_fn.Event[db_fn.Change]):# ...pass

These parameters direct your function to handle writes at a certain path withintheRealtime Database instance.

Path specifications matchall writes that touch apath, including writes that happen anywhere below it. If you set the pathfor your function as/foo/bar, it matches events at both of these locations:

 /foo/bar /foo/bar/baz/really/deep/path

In either case, Firebase interprets that the event occurs at/foo/bar,and the event data includes the old and new data at/foo/bar. If the eventdata might be large, consider using multiple functions at deeper paths insteadof a single function near the root of your database. For the best performance,only request data at the deepest level possible.

Wildcarding and capturing

You can use{key},{key=*},{key=prefix*},{key=*suffix}for capturing.*,prefix*,*suffix for single-segment wildcarding.Note:** represents multi-segment wildcarding, whichRealtime Database does not support.SeeUnderstand path patterns.

Path wildcarding. You can specify a path component as a wildcard:

  • Using asterisk,*. For example,foo/* matches any children one level ofthe node hierarchy belowfoo/.
  • Using a segment containing exactly asterisk,*. For example,foo/app*-usmatches any child segments belowfoo/ withapp prefix and-us suffix.

Paths with wildcards can match multiple events from, for example, a singlewrite. An insert of

{  "foo": {    "hello": "world",    "firebase": "functions"  }}

matches the path"/foo/*" twice: once with"hello": "world" and again with"firebase": "functions".

Path capturing. You can capture path matches into named variables to be usedin your function code (e.g./user/{uid},/user/{uid=*-us}).

The values of the capture variables are available within thedatabase.DatabaseEvent.paramsobject of your function.

Instance wildcarding. You can also specify an instancecomponent using wildcarding. A instance wildcard can have prefix, suffix or both(e.g.my-app-*-prod).

Wildcard and capture reference

WithCloud Functions (2nd gen) andRealtime Database, a pattern can be used whenspecifyingref andinstance. Each trigger interface will have the followingoptions for scoping a function:

SpecifyingrefSpecifyinginstanceBehavior
Single (/foo/bar)Not specifyingScopes handler to all instances in the function region.
Single (/foo/bar)Single (‘my-new-db')Scopes handler to the specific instance in the function region.
Single (/foo/bar)Pattern (‘inst-prefix*')Scopes handler to all instances that match the pattern in the function region.
Pattern (/foo/{bar})Not specifyingScopes handler to all instances in the function region.
Pattern (/foo/{bar})Single (‘my-new-db')Scopes handler to the specific instance in the function region.
Pattern (/foo/{bar})Pattern (‘inst-prefix*')Scopes handler to all instances that match the pattern in the function region.

Handle event data

When aRealtime Database event triggers, it passes anEvent object to your handler function.This object has adata property, which, for creation and deletion events,contains a snapshot of the data created or deleted.

In this example, the function retrieves the data forthe referenced path, converts the string at that location touppercase, and writes that modified string to the database:

Node.js

// Listens for new messages added to /messages/:pushId/original and creates an// uppercase version of the message to /messages/:pushId/uppercase// for all databases in 'us-central1'exports.makeuppercase=onValueCreated("/messages/{pushId}/original",(event)=>{// Grab the current value of what was written to the Realtime Database.constoriginal=event.data.val();logger.log("Uppercasing",event.params.pushId,original);constuppercase=original.toUpperCase();// You must return a Promise when performing// asynchronous tasks inside a function, such as// writing to the Firebase Realtime Database.// Setting an "uppercase" sibling in the// Realtime Database returns a Promise.returnevent.data.ref.parent.child("uppercase").set(uppercase);},);

Python

@db_fn.on_value_created(reference="/messages/{pushId}/original")defmakeuppercase(event:db_fn.Event[Any])->None:"""Listens for new messages added to /messages/{pushId}/original and    creates an uppercase version of the message to /messages/{pushId}/uppercase    """# Grab the value that was written to the Realtime Database.original=event.dataifnotisinstance(original,str):print(f"Not a string:{event.reference}")return# Use the Admin SDK to set an "uppercase" sibling.print(f"Uppercasing{event.params['pushId']}:{original}")upper=original.upper()parent=db.reference(event.reference).parentifparentisNone:print("Message can't be root node.")returnparent.child("uppercase").set(upper)

Reading the previous value

Forwrite orupdate events, thedata propertyis aChange object that contains two snapshotsthat represent the data state before and after the triggering event.TheChange object has abefore property that lets you inspect what wassaved toRealtime Databasebefore the event and anafter property that representsthe state of the dataafter the event happened.

For example, thebefore property can be used to make sure the function onlyuppercases text when it is first created:

Node.js

exportsmakeUppercase=onValueWritten("/messages/{pushId}/original",(event)=>{// Only edit data when it is first created.if(event.data.before.exists()){returnnull;}// Exit when the data is deleted.if(!event.data.after.exists()){returnnull;}// Grab the current value of what was written to the Realtime Database.constoriginal=event.data.after.val();console.log('Uppercasing',event.params.pushId,original);constuppercase=original.toUpperCase();// You must return a Promise when performing asynchronous tasks inside a Functions such as// writing to the Firebase Realtime Database.// Setting an "uppercase" sibling in the Realtime Database returns a Promise.returnevent.data.after.ref.parent.child('uppercase').set(uppercase);});

Python

@db_fn.on_value_written(reference="/messages/{pushId}/original")defmakeuppercase2(event:db_fn.Event[db_fn.Change])->None:"""Listens for new messages added to /messages/{pushId}/original and    creates an uppercase version of the message to /messages/{pushId}/uppercase    """# Only edit data when it is first created.ifevent.data.beforeisnotNone:return# Exit when the data is deleted.ifevent.data.afterisNone:return# Grab the value that was written to the Realtime Database.original=event.data.afterifnothasattr(original,"upper"):print(f"Not a string:{event.reference}")return# Use the Admin SDK to set an "uppercase" sibling.print(f"Uppercasing{event.params['pushId']}:{original}")upper=original.upper()parent=db.reference(event.reference).parentifparentisNone:print("Message can't be root node.")returnparent.child("uppercase").set(upper)

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-17 UTC.