3 minutes
Persistence between runs of Firestore Emulators
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.