Extend Realtime Database with Cloud Functions

With Cloud Functions, you can handle events in the Firebase Realtime Database. Processing database events with Cloud Functions is more flexible than processing on the client side for these reasons:

  • Each change to the database is processed individually.
  • Functions run with administrative privileges, so actions may be performed that bypass the security restrictions of the authenticated user.
  • You can change the behavior anytime you want without having to update client code.

The Realtime Database supports the write event type, which triggers anytime data is created, destroyed, or changed in a specified database location.

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

  1. Waits for changes to a particular database location for write events.
  2. Fires when a write event occurs and performs its tasks (see What can I do with Cloud Functions? for examples of use cases).
  3. Receives an event data object that contains two snapshots of the data stored at the specified path: one with the original data prior to the change, and one with the new data.

Trigger a database function

You create a new Cloud Function for Realtime Database events with functions.database. To control when your Cloud Function should trigger, call ref(string). This method directs your Cloud Function to handle writes at a certain path within your database.


Path specifications match all writes that touch a path, including writes that happen anywhere below it. If you set the path for your function as /foo/bar, it matches writes at both of these locations:


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 event data might be large, consider using multiple functions at deeper paths instead of a single function near the root of your database. For the best performance, only request data at the deepest level possible.

You can specify a path component as a wildcard by surrounding it in curly brackets; ref('foo/{bar}') matches any child of foo. The name of the child is available in your Cloud Function as event.params.bar.

Paths with wildcards can match multiple events from a single write. An insert of

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

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

Handle event data

When handling a Realtime Database event, event.data is a DataDeltaSnapshot. In this example, the function retrieves event.data for the specified path, converts the string at that location to uppercase, and writes that modified string to the location /messages/{pushId}/uppercased:

Reading the previous value

The DataDeltaSnapshot has a previous property that lets you inspect what was saved to the database before the event. The previous property returns a new DataDeltaSnapshot where all DataSnapshot methods (for example, val() and exists()) refer to the previous value. You can read the new value again by either using the original DataDeltaSnapshot or reading the current property on any DataDeltaSnapshot to read a value as it is after the event.

For example, the previous property could be used to make the makeUppercase function an uppercase-only new value:

Monitoring changed values

Sometimes you don't need the old value; you just need to know whether data has changed. You can see if data changed at a path using the changed() function on DataDeltaSnapshot. This Cloud Function only calls createThumbnail if a change to a user profile also changed the value of profilePicture:

exports.thumbnailProfile = functions.database.ref('/profiles/{userID}')
  .onWrite(event => {
  var data = event.data;
  if (!data.changed('profilePicture')) {
  return createThumbnail(data.child('profilePicture').val()).then(function(url) {
    return data.ref.update({profileThumbnail: url});

Send feedback about...

Need help? Visit our support page.