Firestore Indexes Deep Dive — Composite Indexes, Query Performance, and Optimization
In this tutorial, you will learn about Firestore Indexes Deep Dive. We cover key concepts, practical examples, and best practices to help you master this topic.
Firestore indexes are data structures that enable efficient query execution. Single-field indexes are automatic, while Composite indexes must be explicitly created for compound queries involving multiple fields.
What You'll Learn
- How indexes enable fast Firestore queries
- Creating and managing composite indexes
- Optimizing index strategies for performance
Why It Matters
Proper index design is critical for Firestore query performance and cost. Missing indexes cause query failures; excessive indexes slow writes. DodaTech's Firestore databases are optimized with carefully selected composite indexes.
flowchart TD
subgraph "Index Types"
SI["Single-Field Indexes"]
CI["Composite Indexes"]
end
SI -->|"Automatic"| Q1["Simple queries"]
CI -->|"Manual"| Q2["Compound queries"]
subgraph "Cost"
R["Reads: Faster queries"]
W["Writes: Slower per write"]
end
CI --> R
CI --> W
style SI fill:#dbeafe,stroke:#2563eb
style CI fill:#fef08a,stroke:#ca8a04
Code Examples
// Understanding when indexes are needed
// Single-field index: Automatic
const q1 = query(
collection(db, 'users'),
where('role', '==', 'admin')
);
// Composite index needed: (role, createdAt)
const q2 = query(
collection(db, 'users'),
where('role', '==', 'admin'),
orderBy('createdAt', 'desc')
);
// Composite index needed: (isActive, score)
const q3 = query(
collection(db, 'users'),
where('isActive', '==', true),
where('score', '>=', 100),
orderBy('score', 'desc')
);
// firestore.indexes.json - Full configuration
{
"indexes": [
{
"collectionGroup": "users",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "role", "order": "ASCENDING" },
{ "fieldPath": "createdAt", "order": "DESCENDING" }
]
},
{
"collectionGroup": "orders",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "status", "order": "ASCENDING" },
{ "fieldPath": "total", "order": "ASCENDING" },
{ "fieldPath": "createdAt", "order": "DESCENDING" }
]
},
{
"collectionGroup": "products",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "category", "order": "ASCENDING" },
{ "fieldPath": "price", "order": "ASCENDING" }
]
}
],
"fieldOverrides": [
{
"collectionGroup": "logs",
"fieldPath": "message",
"indexes": [
{ "order": "ASCENDING", "queryScope": "COLLECTION" },
{ "order": "DESCENDING", "queryScope": "COLLECTION" }
]
}
]
}
# Manage indexes via CLI
# List current indexes
firebase firestore:indexes
# Export indexes to JSON
firebase firestore:indexes > firestore.indexes.json
# Deploy indexes
firebase deploy --only firestore:indexes
# Delete an index (via config file and redeploy)
# Remove from firestore.indexes.json and redeploy
# Monitoring index usage
from google.cloud import firestore_admin_v1
client = firestore_admin_v1.FirestoreAdminClient()
# List indexes for a database
parent = client.database_path('project-id', '(default)')
indexes = client.list_indexes(parent=parent)
for index in indexes:
fields = [
f'{f.field_path}:{f.order.name}'
for f in index.fields
]
print(f'{index.name}: {", ".join(fields)}')
Common Mistakes
1. Creating Composite Indexes for Every Possible Query
More indexes = slower writes. Index only queries your application actually uses.
2. Not Deleting Unused Indexes
Review and remove indexes that are no longer used by any query.
3. Overlooking Collection Group Indexes
Queries on subcollections need collection group indexes, not regular indexes.
4. Using the Wrong Field Order in Composite Indexes
The field order must match the query: equality fields first, range fields second, orderBy last.
5. Ignoring Index Size Limits
Index entries contribute to document size. Large indexed fields increase storage costs.
Practice Questions
- What indexes are created automatically in Firestore?
- How many fields can a composite index contain?
- What happens when you run a query without a required index?
- How do you create a composite index for a collection group query?
- How do you delete an unused index?
Answers:
- Single-field indexes for every field in every document.
- Up to 8 fields per composite index.
- The query fails with an error and provides a link to create the required index.
- Set queryScope to COLLECTION_GROUP in the index definition.
- Remove it from firestore.indexes.json and redeploy, or delete it in the Console.
Challenge: Analyze your Firestore application's query patterns. Identify all compound queries, create the required composite indexes, remove unused indexes, and measure the performance improvement. Generate an index optimization report.
FAQ
Mini Project
Build a Firestore index optimizer: analyze your application's query patterns by scanning source code, generate the optimal set of composite indexes, compare against existing indexes, produce a diff report, and automatically update firestore.indexes.json.
What's Next
Learn about real-time listeners with onSnapshot for live data updates, then explore batch writes for bulk operations.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro