Firebase Emulator Suite
The Firebase Emulator Suite runs local versions of Firebase services on your development machine. You test Firestore, Authentication, Cloud Functions, Storage, and more without touching your production data or incurring costs. Changes made to the emulator disappear when you stop it, making it safe for experimental testing.
Why Use the Emulator
Testing against production Firebase services has three problems: it modifies real data, it incurs usage costs, and it is slow due to network latency. The emulator solves all three:
Without Emulator: Test creates a user ---> Production Firebase Auth gets a real user Test writes data ---> Production Firestore gets test records Test triggers function ---> Real Cloud Function runs, billing counts Result: Production polluted with test data, money spent With Emulator: Test creates a user ---> Local Auth emulator only Test writes data ---> Local Firestore emulator only Test triggers function ---> Local Functions emulator Result: No production impact, no cost, instant response
Installing the Emulator Suite
# Firebase CLI must be installed npm install -g firebase-tools # Initialize emulators in your project firebase init emulators
Firebase asks which emulators to install:
- Authentication Emulator — port 9099
- Firestore Emulator — port 8080
- Realtime Database Emulator — port 9000
- Cloud Functions Emulator — port 5001
- Storage Emulator — port 9199
- Hosting Emulator — port 5000
- Pub/Sub Emulator — port 8085
Select the ones you need. Firebase adds an emulators section to your firebase.json.
Starting the Emulators
firebase emulators:start
The terminal shows each emulator starting on its port. A local Emulator UI opens at http://localhost:4000 — a browser-based dashboard where you browse data, view function logs, and manage auth users.
Firebase Emulators: ┌────────────────────────┬───────────────────────────────┐ │ Emulator │ Host:Port │ ├────────────────────────┼───────────────────────────────┤ │ Authentication │ localhost:9099 │ │ Firestore │ localhost:8080 │ │ Cloud Functions │ localhost:5001 │ │ Storage │ localhost:9199 │ │ Emulator UI │ localhost:4000 │ └────────────────────────┴───────────────────────────────┘
Connecting Your App to the Emulators
Tell your app to use the local emulators instead of production Firebase services:
import { initializeApp } from "firebase/app";
import { getAuth, connectAuthEmulator } from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getFunctions, connectFunctionsEmulator } from "firebase/functions";
import { getStorage, connectStorageEmulator } from "firebase/storage";
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const functions = getFunctions(app);
const storage = getStorage(app);
// Only connect to emulators in development
if (process.env.NODE_ENV === "development") {
connectAuthEmulator(auth, "http://localhost:9099");
connectFirestoreEmulator(db, "localhost", 8080);
connectFunctionsEmulator(functions, "localhost", 5001);
connectStorageEmulator(storage, "localhost", 9199);
}
All Firebase calls from your app now go to the local emulators. Production data is untouched.
Importing and Exporting Emulator Data
Seed the emulator with test data from a file so every test run starts with a consistent state:
# Export current emulator data to a folder firebase emulators:export ./emulator-data # Start emulators with data pre-loaded firebase emulators:start --import=./emulator-data
Create a seed script that populates the emulator with realistic test data — a few users, some posts, sample settings — and export it once. Every developer on your team imports the same data for consistent testing.
Testing Security Rules with the Emulator
The emulator enforces your actual security rules from firestore.rules and storage.rules. Write automated rule tests:
const { initializeTestEnvironment } = require("@firebase/rules-unit-testing");
const testEnv = await initializeTestEnvironment({
projectId: "my-project",
firestore: {
rules: require("fs").readFileSync("firestore.rules", "utf8"),
host: "localhost",
port: 8080
}
});
// Test as an authenticated user
const aliceDb = testEnv.authenticatedContext("alice_uid").firestore();
// Write should succeed — Alice can write her own document
await firebase.assertSucceeds(
aliceDb.collection("users").doc("alice_uid").set({ name: "Alice" })
);
// Test as an unauthenticated user
const unauthDb = testEnv.unauthenticatedContext().firestore();
// Write should fail — unauthenticated users cannot write user documents
await firebase.assertFails(
unauthDb.collection("users").doc("alice_uid").set({ name: "Fake Alice" })
);
Key Takeaway
The Firebase Emulator Suite provides local versions of every Firebase service for safe, free, fast development testing. Start emulators with firebase emulators:start, connect your app using the connect*Emulator functions in development mode, and use the Emulator UI to inspect data and logs. Export realistic seed data once and import it on every emulator start for consistent test conditions. Write automated security rule tests using the rules testing library against the local Firestore emulator.
