logo
Firebase - Interview Questions and Answers
How do you optimize Firebase Firestore queries?
Optimizing Firestore Queries for Performance and Cost

Firestore is a NoSQL database that scales automatically, but poorly optimized queries can be slow and expensive. Here’s how to optimize Firestore queries for speed, cost-efficiency, and scalability.

1. Use Indexes Properly
* Firestore automatically indexes fields but composite queries require custom indexes.
  • If you see an error like:

    "The query requires an index."

  • Go to Firebase Console → Firestore → Indexes → Add Index.
Example: Composite Index

For querying users by city & age, create an index on { city, age }.

const usersRef = db.collection("users")
    .where("city", "==", "New York")
    .where("age", ">=", 25);

* Avoid auto-indexing unnecessary fields to reduce storage costs.


2. Fetch Only Required Data (Projection)
Bad: Retrieving unnecessary fields
const userSnapshot = await db.collection("users").get();

* This retrieves ALL user data (slow + expensive).

Good: Select only needed fields
const userSnapshot = await db.collection("users")
    .select("name", "email") // Fetch only required fields
    .get();

* Less data transfer = faster queries & lower costs.


3. Paginate Large Queries

Fetching large datasets can cause performance bottlenecks.

* Use .limit() and .startAfter() for pagination
const firstPage = await db.collection("posts")
    .orderBy("timestamp")
    .limit(10)
    .get();

const lastDoc = firstPage.docs[firstPage.docs.length - 1];

const secondPage = await db.collection("posts")
    .orderBy("timestamp")
    .startAfter(lastDoc)
    .limit(10)
    .get();

* Benefits: Avoids fetching unnecessary data, improves UX.


4. Use Array Membership Instead of Multiple Queries
* Bad: Querying each user separately
const user1 = db.collection("users").where("id", "==", "123").get();
const user2 = db.collection("users").where("id", "==", "456").get();
* Good: Use array-contains-any
const users = db.collection("users")
    .where("id", "in", ["123", "456"])
    .get();

* Less read operations = lower cost & better performance.


5. Avoid IN Queries with Large Lists

Firestore allows in queries with up to 30 elements.

* Alternative: Use Subcollections

Instead of storing a large array of IDs, create a subcollection.

/groups/{groupId}/members/{userId}

Now query directly:

db.collection("groups").doc("group123").collection("members").get();

* Faster lookups & better scalability.


6. Batch Reads & Writes

Instead of multiple separate requests, use batch operations.

* Example: Batch Write
const batch = db.batch();

const userRef1 = db.collection("users").doc("user1");
const userRef2 = db.collection("users").doc("user2");

batch.update(userRef1, { points: 100 });
batch.update(userRef2, { points: 200 });

await batch.commit();

* Single request instead of multiple = Faster & Cheaper.


7. Use Caching for Faster Queries

Firestore supports offline persistence.

* Enable caching in Firestore SDK
firebase.firestore().enablePersistence();

* Reduces network calls by storing data locally.


8. Stream Data Instead of Fetching in Bulk

Instead of fetching the entire dataset, use real-time listeners.

* Example: Real-time listener
db.collection("messages").where("roomId", "==", "123")
    .onSnapshot(snapshot => {
        snapshot.docChanges().forEach(change => {
            console.log("New Message: ", change.doc.data());
        });
    });

* Only gets new/changed data instead of refetching everything.


9. Structure Firestore for Fast Queries
  • Use subcollections for frequently queried data.
  • Avoid deeply nested documents (Firestore has a 1MB document size limit).
  • Denormalize data when necessary to reduce reads.

Summary of Optimizations :
Optimization Benefit
Use Indexes Faster composite queries
Select only needed fields Reduces data transfer
Paginate queries Avoids large reads
Use array-contains-any Fewer queries, better efficiency
Batch operations Reduces network requests
Enable caching Faster queries, offline support
Use real-time listeners Avoids full dataset fetches
Optimize Firestore structure Better performance & scalability