Google is committed to advancing racial equity for Black communities. See how.

Testing Security Rules with the Realtime Database Emulator

The Realtime Database emulator is intended to make it easier to write unit tests that check the behavior of your database security rules.

When the emulator starts up, your database will be "open" from a security perspective (all reads and writes are allowed). You can change the security rules in a unit testing framework using the Firebase Test SDK module, see below.

Differences between the emulator and production

  1. You do not have to explicitly create a database instance. The emulator will automatically create any database instance that is accessed.
  2. Each new database is started with open rules, so any user will be able to read or write to any path.
  3. Each emulated database applies the Spark plan limits and quotas (most notably, this limits each instance to 100 concurrent connections).
  4. Any database will accept the string "owner" as an admin auth token.
    1. If you want to use the REST api as an admin, include the header
      Authorization: Bearer owner.
    2. You can use this to set rules using curl. Assuming your rules are in a database.rules.json file, this should work:
      curl -X PUT -H 'Authorization: Bearer owner' --data @database.rules.json http://localhost:9000/.settings/rules.json?ns=<name>
  5. The database emulator does not have working interaction with other Firebase products. Notably, the normal Firebase auth flow will not work. Instead, in the Firebase Test SDK, we have provided the initializeTestApp() method in the testing module, which takes an auth field. The Firebase handle created using this method will behave as though it has successfully authenticated as whatever entity you provide. If you pass in null, it will behave as an unauthenticated user (auth != null rules will fail, for example).

Install the emulator

To install the Realtime Database emulator, use the Firebase CLI and run the command below:

firebase setup:emulators:database

Run the emulator

Start the emulator using the following command. The emulator will run until you kill the process:

firebase emulators:start --only database

Note that the Realtime Database emulator requires Java 8 or higher.

In many cases you want to start the emulator, run a test suite, and then shut down the emulator after the tests run. You can do this easily using the emulators:exec command:

firebase emulators:exec --only database "./"

When started the emulator will attempt to run on a default port (9000). You can change the emulator port by modifying the "emulators" section of your firebase.json file:

  // ...
  "emulators": {
    "database": {
      "port": "YOUR_PORT"

Interact with the emulator

A normal Firebase Realtime Database instance is accessible at a subdomain of, and you can access the REST api like this:


The emulator runs locally, and is available at localhost:9000. To interact with a specific database instance, you will have to use a query parameter to specify the database name.


We've provided the @firebase/testing module to make it easier to interact with the emulator using the Firebase SDK. The @firebase/testing module allows you to interact with a locally running version of the Realtime Database emulator. If you get timeouts or ECONNREFUSED errors, double check that the emulator is running.

We strongly recommend using a recent version of Node.js to allow you to use async/await notation. Almost all of the behavior you might want to test involves asynchronous functions, and the testing module is designed to work with Promise-based code.

The module exposes the following methods:

initializeTestApp({ databaseName: , auth: }) => FirebaseApp

Use this to create an app authenticated as a specific user to use in tests.

Returns an initialized firebase app corresponding to the database name and auth variable override specified in options. Note that this does NOT use databaseURL, as it is not running against a remote server.

  databaseName: "my-database",
  auth: { uid: "alice" }

initializeAdminApp({ databaseName: }) => FirebaseApp

Use this to create an app authenticated as an admin to set up state for tests.

Returns an initialized admin firebase app corresponding to the database name specified in options. This app bypasses security rules when reading and writing to the database.

firebase.initializeAdminApp({ databaseName: "my-database" });

loadDatabaseRules({ databaseName: , rules: }) => Promise

Use this to set your database's rules.

Sends rules to a locally running database. Takes an options object that specifies your "databaseName" and your "rules" as strings.

        databaseName: "my-database",
        rules: "{'rules': {'.read': false, '.write': false}}"

apps() => [FirebaseApp]

Returns all the currently initialized test and admin apps.

Use this to clean up apps between or after tests (note that initialized apps with active listeners prevent JavaScript from exiting):

 Promise.all(firebase.apps().map(app => app.delete()))

assertFails(pr: Promise) => Promise

Returns a promise that is rejected if the input succeeds and succeeds if the input is rejected.

Use this to assert that a database read or write fails:


assertSucceeds(pr: Promise) => Promise

Returns a promise that succeeds if the input succeeds and is rejected if the input is rejected.

Use this to assert that a database read or write succeeds:


Generate test reports

After running a suite of tests, you can access test coverage reports that show how each of your security rules was evaluated. To get the reports, query an exposed endpoint on the emulator while it's running. For a browser-friendly version, use the following URL:


This breaks your rules into expressions and subexpressions that you can mouseover for more information, including number of executions and values returned. For the raw JSON version of this data, include the following URL in your query:



If you just want to get a minimal example working, try the JavaScript quickstart.