Skip to content

Firestore Composite Indexes — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Firestore Composite Indexes. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

Your Firestore compound query (multiple where + orderBy) throws FAILED_PRECONDITION — you need a Composite index.

Wrong Approach ❌

// Complex query without composite index
db.collection("products")
    .whereEqualTo("category", "electronics")
    .whereGreaterThan("price", 100)
    .orderBy("price")
    .orderBy("name")
    .limit(50)
    .get()

Output: FirebaseFirestoreException: FAILED_PRECONDITION: The query requires an index.

Right Approach ✅

class ProductRepository(private val db: FirebaseFirestore) {

    data class QueryConfig(
        val fields: List<String>,
        val orders: List<Pair<String, Direction>>,
        val filters: List<String>
    )

    // Before running query, ensure index exists
    suspend fun getFilteredProducts(
        category: String,
        minPrice: Double,
        sortBy: String = "price"
    ): List<Product> {
        return try {
            db.collection("products")
                .whereEqualTo("category", category)
                .whereGreaterThan("price", minPrice)
                .orderBy("price")
                .orderBy("name")
                .limit(50)
                .get().await()
                .toObjects(Product::class.java)
        } catch (e: FirebaseFirestoreException) {
            if (e.code == Code.FAILED_PRECONDITION) {
                // Extract index creation link from error message
                val indexLink = extractIndexLink(e.message ?: "")
                Log.e("Firestore", "Create index: $indexLink")
                // Prompt user or log for developer
            }
            emptyList()
        }
    }

    // Index configuration (firestore.indexes.json)
    // {
    //   "indexes": [
    //     {
    //       "collectionGroup": "products",
    //       "queryScope": "COLLECTION",
    //       "fields": [
    //         { "fieldPath": "category", "order": "ASCENDING" },
    //         { "fieldPath": "price", "order": "ASCENDING" },
    //         { "fieldPath": "name", "order": "ASCENDING" }
    //       ]
    //     }
    //   ]
    // }

    // Rules for indexes:
    // 1. Equality fields must come before range/order fields
    // 2. OrderBy fields must be in the same order as the index
    // 3. Fields in WHERE with equality can be in any order

    private fun extractIndexLink(message: String): String {
        val pattern = Regex("https://console\\.firebase\\.google\\.com[^\\s]+")
        return pattern.find(message)?.value ?: "Firebase Console > Firestore > Indexes"
    }
}

Output: Queries succeed after Composite index is created.

Prevention

  • Create Composite indexes for any query with where + orderBy on different fields.
  • The error message includes a direct link to create the required index.
  • Deploy indexes via <a href="/apis/firebase/">Firebase</a> deploy --only firestore:indexes using firestore.indexes.json.
  • Monitor index usage in Firebase Console.

Common Mistakes with firestore index

  1. Mixing let bindings with <- bindings in do notation, producing type errors
  2. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  3. Non-exhaustive pattern matches that compile with warnings then crash at runtime

These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What is the difference between single-field and Composite indexes?

Single-field indexes are auto-created for simple queries. Composite indexes are needed for queries with multiple where clauses or where + orderBy on different fields.

### How many Composite indexes can I have?

Up to 200 Composite indexes per database. Each index can include up to 100 fields.

### How do I create an index from the error message?

Click the link in the error log, or go to Firebase Console > Firestore > Indexes > Add Index. The index configuration must match the query fields and order.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro