Fuego

Index management

big-idea

Overview

Fuego’s Index Management feature provides a visual interface to view, create, and manage Firestore composite indexes across your databases. Instead of manually editing firestore.indexes.json files or navigating the Firebase Console, you can manage all your indexes in one place with instant visibility into their status and configuration.

Use cases:

  • View all composite indexes across collections at a glance
  • Compare index configurations between different databases (example: production vs. staging)
  • Create new composite indexes for complex queries without leaving Fuego
  • Identify missing indexes when syncing environments
  • Manage vector indexes for AI/ML applications

Prerequisites

  • Firestore enabled in your Firebase project
  • Appropriate permissions to manage indexes (Firebase project owner or editor role)
  • Basic understanding of Firestore composite indexes and query requirements

Understanding Firestore indexes

Single-field indexes

Firestore automatically creates single-field indexes for each field in your documents. These handle simple queries with one filter or sort operation.

Composite indexes

Composite indexes are required when your queries include:

  • Multiple equality filters (where() clauses)
  • A mix of equality and inequality filters
  • Multiple orderBy() clauses
  • Array membership checks combined with sorting

Example requiring a composite index:

// This query needs a composite index on (status, createdAt)
const q = query(
  collection(db, "orders"),
  where("status", "==", "pending"),
  orderBy("createdAt", "desc"),
);

Vector indexes

Vector indexes enable similarity searches for AI/ML applications. They support storing and querying high-dimensional embeddings (typically 256, 512, or 1536 dimensions).

Viewing indexes

Access the index management interface

  1. Open Fuego and connect to your Firebase project
  2. Navigate to the database you want to inspect
  3. Click the Index menù item: Index management

Understanding the index list

The index list displays all composite indexes with the following information:

  • Collection ID: The collection where the index is applied
  • Fields: All fields included in the index with their configuration:
    • Ascending/Descending sort order
    • Array membership
    • Vector dimensions (for vector fields)
  • Scope: Whether the index applies to a single collection or collection group
  • Index ID: The unique identifier assigned by Firestore
  • State: Current status of the index (Ready, Creating, Error)

Index list

Filtering indexes

Use the filter dropdowns to narrow down the list:

  • Collection filter: Shows all collections by default
  • Fields filter: Shows all field combinations by default

This helps you quickly find specific indexes when working with large projects.

Comparing indexes across databases

When to use index comparison

Compare indexes when you need to:

  • Sync index configurations between production and staging environments
  • Verify that all required indexes exist in a new environment
  • Audit differences between database instances
  • Prepare for environment migrations

Enable compare mode

  1. Click “Compare indexes with another database” button at the bottom of the index list
  2. Select the two databases you want to compare using the dropdown selectors
  3. Review the comparison results

Index: compare mode

Understanding comparison results

The comparison view shows three status indicators:

Missing (gray badge): The index exists in one database but not the other

  • Click the + button to add the missing index to the target database

Ready (green badge): The index exists and is operational in the database

Creating: The index is being built by Firestore (can take minutes to hours for large collections)

Syncing indexes between databases

To copy an index from one database to another:

  1. Locate the row showing a “Missing” status
  2. Click the + button in the column where the index is missing
  3. Confirm the index creation
  4. Wait for Firestore to build the index (status will change from “Creating” to “Ready”)

⚠️ Important: Index creation is not instantaneous. Large collections may require significant time for index building. Monitor the status to know when queries using the index will work.

Creating new indexes

When you need a new index

Create a composite index when Firestore rejects a query with an error like:

The query requires an index. You can create it here: [link]

Rather than following the Firebase Console link, you can create the index directly in Fuego.

Create a composite index

  1. Click “Create new index” button
  2. Fill in the index configuration:

Collection ID

Select the collection where the index will be applied:

Example: orders, users, products

Fields to index

Add each field that participates in the query:

For standard fields:

  • Attribute: The field name (e.g., status, createdAt, userId)
  • Sort order:
    • Ascending: For queries with orderBy('field', 'asc')
    • Descending: For queries with orderBy('field', 'desc')
    • Arrays: For fields used with array-contains or array-contains-any

For vector fields:

  • Attribute: The field name (e.g., embedding, textVector)
  • Type: Select “Vector”
  • Vector dimensions: Enter the embedding size (232, 256, 512, 768, 1536, etc.). Firestore limit is 2048

Example configuration:

  • Field 1: code (Ascending)
  • Field 2: orderUIDs (Arrays)
  • Field 3: embedding (Vector, 232 dimensions)

Query scope

Select where the index applies:

  • Collection: Index applies only to queries on the specific collection path
  • Collection group: Index applies to all collections with this name, regardless of path
TIP

Collection group indexes enable queries across all collections with the same name. For example, a collection group query on “comments” would search posts/{postId}/comments AND articles/{articleId}/comments.

  1. Click “Add field” to include additional fields
  2. Click “Confirm” to create the index

Index creation

Index creation process

After clicking Confirm:

  1. Fuego submits the index configuration to Firestore
  2. Firestore begins building the index (status: “Creating”)
  3. When complete, status changes to “Ready”
  4. Queries using the index will now succeed

Build time considerations:

  • Empty collections: Seconds
  • Small collections (<1000 documents): Minutes
  • Large collections (>100,000 documents): Hours
  • Very large collections (millions of documents): Can take several hours

Advanced usage

Creating vector indexes for AI applications

Vector indexes enable similarity search for embeddings generated by AI models.

Common use case: Semantic search over product descriptions

import { getFirestore, collection, query, where } from "firebase/firestore";

// Assume you've generated embeddings for user query
const searchEmbedding = await generateEmbedding(userQuery);
// [0.123, 0.456, ...]

// Query using vector similarity
const productsRef = collection(db, "products");
const q = query(
  productsRef,
  where("embedding", "vector-distance", searchEmbedding),
  limit(10),
);

Index configuration in Fuego:

  • Collection ID: products
  • Fields:
    1. embedding (Vector, 1536 dimensions) // OpenAI text-embedding-3-small
    2. category (Ascending) // Optional: filter by category

Multi-field composite indexes

For complex queries combining multiple filters and sorts:

// Query requires composite index on (userId, status, createdAt)
const q = query(
  collection(db, "orders"),
  where("userId", "==", currentUser.uid),
  where("status", "==", "pending"),
  orderBy("createdAt", "desc"),
);

Index configuration:

  • Collection ID: orders
  • Fields:
    1. userId (Ascending)
    2. status (Ascending)
    3. createdAt (Descending)
  • Query scope: Collection

Key principle: Fields used in equality filters come first, followed by the field used for range filtering or sorting.

Array indexes

For queries using array membership:

// Query requires composite index on (tags, publishedAt)
const q = query(
  collection(db, "articles"),
  where("tags", "array-contains", "firebase"),
  orderBy("publishedAt", "desc"),
);

Index configuration:

  • Collection ID: articles
  • Fields:
    1. tags (Arrays)
    2. publishedAt (Descending)

Best practices

Performance

  • Index only what you query: Each index adds storage overhead and write cost. Don’t create indexes for unused queries.
  • Consider query frequency: Create indexes for common queries first. Rare queries might not justify the index maintenance cost.

  • Monitor index usage: Periodically review and remove unused indexes using the Firebase Console’s index usage metrics.

Security

  • Indexes don’t bypass security rules: Even with indexes, security rules must allow the query. A well-indexed query can still be denied if rules don’t permit access.

  • Consider data visibility: Collection group indexes may expose data across security boundaries. Ensure your security rules account for this.

Scalability

  • Plan for growth: Vector indexes on large collections can be expensive. Consider partitioning data or using selective indexing.

  • Understand write impact: Each indexed field adds to write costs. A document with 5 composite indexes costs more to write than one with 1.

  • Test in staging: Always create and test indexes in a staging environment before applying to production, especially for large collections.

Development workflow

  • Use compare mode regularly: Before deploying, ensure staging and production indexes match to prevent query failures.

  • Document index purposes: Add comments in your codebase linking queries to their required indexes.

  • Version control index definitions: Export firestore.indexes.json and commit it to your repository for team visibility.

    firebase firestore:indexes > firestore.indexes.json
    

Error handling

Index creation fails

Error message:

Failed to create index: Permission denied

Cause: Insufficient Firebase project permissions

Solution: Ensure your Firebase account has Owner or Editor role:

  1. Go to Firebase Console → Project Settings → Users and Permissions
  2. Verify your role is Owner or Editor
  3. If not, request elevated permissions from project owner

Query still fails after index creation

Error message:

The query requires an index. You can create it here: [link]

Cause: Index is still building or configuration doesn’t match the query

Solution:

  1. Check the index status in Fuego - wait if status is “Creating”
  2. Verify field order matches your query exactly
  3. Ensure ascending/descending directions match
  4. Check that query scope (collection vs. collection group) matches index scope

Index stuck in “Creating” status

Symptoms: Index remains in “Creating” state for extended period

Solution:

  1. For large collections, this is normal - wait longer (check Firebase Console for estimated completion)
  2. If stuck for days, check Firebase Console for error messages
  3. Delete and recreate the index if it appears hung
  4. Contact Firebase support if the issue persists

Troubleshooting

Missing indexes after comparing databases

Symptoms: Indexes show as “Missing” in comparison but you’re sure they exist

Solution: Refresh the index list to ensure you’re viewing the latest state:

  1. Close and reopen the compare mode
  2. Verify you’ve selected the correct database in the dropdown
  3. Check the Firebase Console to confirm the index actually exists

Cannot create vector index

Symptoms: Vector index creation fails or option is disabled

Solution:

  1. Verify your Firebase project supports vector search (requires Blaze plan)
  2. Ensure vector dimensions are supported (check Firebase documentation for valid ranges)
  3. Confirm the field doesn’t already have a different index type

Index comparison shows too many differences

Symptoms: Staging and production show vastly different indexes

Solution: This likely indicates environments have diverged:

  1. Review your deployment process to ensure indexes sync automatically
  2. Consider exporting production indexes and importing to staging
  3. Use Fuego’s sync feature to selectively copy critical indexes

Complete example

Here’s a complete workflow for managing indexes in a production application:

Scenario: E-commerce order tracking

Requirements:

  • Users need to see their orders filtered by status and sorted by date
  • Support search queries that find orders by multiple criteria
  • Admin dashboard shows all pending orders across all users

Step 1: Identify required indexes

// User order history query
const userOrders = query(
  collection(db, "orders"),
  where("userId", "==", currentUser.uid),
  where("status", "in", ["pending", "processing", "shipped"]),
  orderBy("createdAt", "desc"),
  limit(20),
);
// Requires: userId (=), status (=), createdAt (desc)

// Admin pending orders query
const pendingOrders = query(
  collectionGroup(db, "orders"),
  where("status", "==", "pending"),
  orderBy("createdAt", "asc"),
);
// Requires: status (=), createdAt (asc) with collection group scope

Step 2: Create indexes in Fuego

In Fuego’s index management:

Index 1 - User Order History:

Collection ID: orders
Fields:
  1. userId (Ascending)
  2. status (Ascending)
  3. createdAt (Descending)
Query scope: Collection

Index 2 - Admin Pending Orders:

Collection ID: orders
Fields:
  1. status (Ascending)
  2. createdAt (Ascending)
Query scope: Collection group

Step 3: Verify in staging

  1. Create indexes in staging database
  2. Wait for “Ready” status
  3. Test queries in your application
  4. Use Fuego’s compare mode to verify configuration

Step 4: Deploy to production

  1. Open compare mode in Fuego
  2. Select staging and production databases
  3. Click + to copy indexes from staging to production
  4. Monitor status until all indexes show “Ready”
  5. Deploy application code that uses the queries

Step 5: Maintain indexes

Periodically review indexes:

  • Remove unused indexes to reduce storage costs
  • Add new indexes as features evolve
  • Keep staging and production synchronized

API reference

While Fuego provides a visual interface, you can also manage indexes programmatically using the firebase CLI and firestore.indexes.json file.

firestore.indexes.json structure

{
  "indexes": [
    {
      "collectionGroup": "orders",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "userId",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "status",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "createdAt",
          "order": "DESCENDING"
        }
      ]
    }
  ],
  "fieldOverrides": []
}

Deploying indexes with Firebase CLI

# Deploy indexes defined in firestore.indexes.json
firebase deploy --only firestore:indexes

# Deploy to specific project
firebase use production
firebase deploy --only firestore:indexes

External resources


Found an issue or have suggestions? Report feedback to help improve Fuego’s index management features.