Firebase Emulators is a great recent addition to Firebase, that allows you to keep your development workflow 100% local and offline-friendly, despite depending on Cloud Firestore and other closed-source services within the Firebase offering.

However, the fact it resets itself to an empty state between every launch get old quickly. Especially you’re on a laptop or resource constrained machine, that might happen several times a day.

So how do you bootstrap your emulators to a useful state every time?

One way to do it is to use firebase emulators:exec ./bootstrap-data.sh instead of the regular emulators:start command and write a tiny application that knows how to set up users and docs.

But there’s a better way!

We can export the current state into a directory on disk by running firebase emulators:export ./data

and we can also restore our snapshot with firebase emulators:start --import=./dir

there’s even an --export-on-exit flag that automates this.

Be aware though, that if the emulators don’t shut down gracefully you lose everything since launch! unlike with a typical database, where you in general are mainly at risk of losing the last few seconds of data in such a scenario. This is since emulators are in-memory by design and only does --export-on-exit if the shutdown is graceful.

Also note that if you run firebase emulators:start directly, then --export-on-exit works fine if you press Ctrl-C once to shut down. But if you run firebase emulators:start from within a shellscript, and you press Ctrl-C, then the script will not trigger a graceful shutdown by default and --export-on-exit will not work! Unless you trap the SIGINT from Ctrl-C and relay it to the emulators process.

For the same reason is not a good idea to be impatient and press Ctrl-C multiple times, since that sends a more insisting kill signal and bypasses --export-on-exit.

Despite all of the weaknesses, automatic export / import is a great mitigiation to what’s otherwise somewhat of a productivity sinkhole.

Putting it all together

At least at the time of writing, if the import/export data directory you point to does not exist, emulators fail to launch, without giving a proper error message. And if you create the directory but leave it empty, --export-on-exit seems to do nothing.

So start out by running firebase emulators:start and then in a separate window, do a manual export once: firebase emulators:export ./data. With that in place our strategy should work After that it is as easy as:

standalone:

firebase emulators:start --import=./data --export-on-exit

or when used in a script:

…it gets slightly more verbose since we want to relay SIGINT to emulators to ensure --export-on-exit works:

#!/bin/bash

set -e

function shutdown {
  echo "Shutting down emulators from entry script..."
  # ps aux
  kill -2 $pid
  wait $pid
  echo "Shutdown completed successfully"
}

trap shutdown EXIT

firebase emulators:start --import=./data --export-on-exit &

pid=$!
echo "Got emulators pid $pid"

wait $pid



sponsor

Need private photo sharing that's not tied up in the social media circus? Photoroll is a good way to share photos with your clients.
Or privately gather media from participants of weddings and other small to medium-sized events.