Realtime Database Triggers

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 onWrite() event, 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(path). This method directs your Cloud Function to handle writes at a certain path within your database:

functions.database.ref('/foo/bar')

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:

 /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 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 with curly brackets; ref('foo/{bar}') matches any child of /foo. The values of these wildcard path components are available within the event.params object of your Cloud Function. In this example, the value is available 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 DeltaSnapshot. 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 DeltaSnapshot has a previous property that lets you inspect what was saved to the database before the event. The previous property returns a new DeltaSnapshot where all methods (for example, val() and exists()) refer to the previous value. You can read the new value again by either using the original DeltaSnapshot or reading the current property on any DeltaSnapshot 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 DeltaSnapshot. 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 eventSnapshot = event.data;
    var profilePictureSnapshot = eventSnapshot.child('profilePicture');
    if (profilePictureSnapshot.changed()) {
      return createThumbnail(profilePictureSnapshot.val())
        .then(url => {
          return eventSnapshot.ref.update({ profileThumbnail: url });
        });
    }
  });

Send feedback about...

Need help? Visit our support page.