# How to Use Firebase with Algolia for Full-Text Search

- Tool: Firebase
- Difficulty: Intermediate
- Time required: 20-25 min
- Compatibility: Firebase JS SDK v9+, Cloud Functions v2, Algolia algoliasearch v4+, Node.js 18+
- Last updated: March 2026

## TL;DR

To add full-text search to Firebase, sync your Firestore data to Algolia using a Cloud Function that triggers on document writes. Each time a document is created, updated, or deleted, the function mirrors the change in an Algolia index. On the client side, use Algolia's InstantSearch library for real-time search UI with facets, highlighting, and typo tolerance that Firestore cannot provide natively.

## Adding Full-Text Search to Firebase with Algolia

Firestore does not support full-text search natively. The standard solution is to sync Firestore data to a dedicated search service like Algolia, which provides typo tolerance, faceted filtering, and sub-50ms query times. This tutorial shows you how to create Firestore triggers that keep an Algolia index in sync and how to build a search interface using Algolia's InstantSearch React library.

## Before you start

- A Firebase project on the Blaze plan (required for Cloud Functions and outbound network calls)
- An Algolia account with an application ID and Admin API Key (free tier available)
- Cloud Functions initialized in your project (firebase init functions)
- Node.js 18+ installed

## Step-by-step guide

### 1. Install Algolia SDK in your functions directory

Navigate to your functions directory and install the Algolia search client. This package runs server-side inside Cloud Functions. You will use the Admin API key to write to the Algolia index, so it must never be exposed to the client.

```
cd functions
npm install algoliasearch
```

**Expected result:** algoliasearch is added to functions/package.json dependencies.

### 2. Store Algolia credentials as secrets

Use Firebase's defineSecret to store your Algolia Application ID and Admin API Key in Cloud Secret Manager. This avoids hardcoding sensitive values and makes them available to your Cloud Functions at runtime.

```
// functions/src/index.ts
import { defineSecret } from 'firebase-functions/params'

const ALGOLIA_APP_ID = defineSecret('ALGOLIA_APP_ID')
const ALGOLIA_ADMIN_KEY = defineSecret('ALGOLIA_ADMIN_KEY')

// Set the secrets:
// firebase functions:secrets:set ALGOLIA_APP_ID
// firebase functions:secrets:set ALGOLIA_ADMIN_KEY
```

**Expected result:** Secrets are stored in Cloud Secret Manager and accessible in your function code.

### 3. Create a Firestore trigger to sync data to Algolia

Write a Cloud Function v2 that fires on document writes in your target collection. On create and update events, the function saves the document data plus its Firestore ID as the Algolia objectID. On delete, it removes the record from the index. The function must declare the secrets it needs in its options.

```
// functions/src/index.ts
import { onDocumentWritten } from 'firebase-functions/v2/firestore'
import algoliasearch from 'algoliasearch'

const ALGOLIA_APP_ID = defineSecret('ALGOLIA_APP_ID')
const ALGOLIA_ADMIN_KEY = defineSecret('ALGOLIA_ADMIN_KEY')
const ALGOLIA_INDEX_NAME = 'products'

export const syncToAlgolia = onDocumentWritten(
  {
    document: 'products/{productId}',
    secrets: [ALGOLIA_APP_ID, ALGOLIA_ADMIN_KEY]
  },
  async (event) => {
    const client = algoliasearch(
      ALGOLIA_APP_ID.value(),
      ALGOLIA_ADMIN_KEY.value()
    )
    const index = client.initIndex(ALGOLIA_INDEX_NAME)
    const { productId } = event.params

    // Document was deleted
    if (!event.data?.after.exists) {
      await index.deleteObject(productId)
      return
    }

    // Document was created or updated
    const data = event.data.after.data()
    await index.saveObject({
      objectID: productId,
      ...data
    })
  }
)
```

**Expected result:** Every Firestore write to the products collection is mirrored to the Algolia index.

### 4. Configure Algolia index settings

Set searchable attributes and ranking criteria in the Algolia dashboard or programmatically. This tells Algolia which fields to search and how to rank results. Configure this once; the settings persist across all future indexing operations.

```
// One-time setup script (run locally)
import algoliasearch from 'algoliasearch'

const client = algoliasearch('YOUR_APP_ID', 'YOUR_ADMIN_KEY')
const index = client.initIndex('products')

await index.setSettings({
  searchableAttributes: ['name', 'description', 'category'],
  attributesForFaceting: ['category', 'price'],
  customRanking: ['desc(createdAt)']
})
```

**Expected result:** Algolia searches the name, description, and category fields and supports faceted filtering on category and price.

### 5. Build the search UI with InstantSearch

Install Algolia's InstantSearch library for your frontend framework and create a search component. Use the Search-Only API Key (not the Admin key) for client-side queries. InstantSearch provides pre-built widgets for search boxes, hit lists, facet filters, and pagination.

```
npm install algoliasearch react-instantsearch

// src/components/Search.tsx
import algoliasearch from 'algoliasearch/lite'
import { InstantSearch, SearchBox, Hits, Highlight } from 'react-instantsearch'

const searchClient = algoliasearch(
  import.meta.env.VITE_ALGOLIA_APP_ID,
  import.meta.env.VITE_ALGOLIA_SEARCH_KEY
)

function Hit({ hit }: { hit: any }) {
  return (
    <div>
      <h3><Highlight attribute="name" hit={hit} /></h3>
      <p>{hit.description}</p>
    </div>
  )
}

export function Search() {
  return (
    <InstantSearch searchClient={searchClient} indexName="products">
      <SearchBox placeholder="Search products..." />
      <Hits hitComponent={Hit} />
    </InstantSearch>
  )
}
```

**Expected result:** A search box appears that queries Algolia in real-time and displays matching products with highlighted terms.

### 6. Deploy and test the sync function

Deploy your Cloud Function and create a test document in Firestore. Check the Algolia dashboard to verify the document appears in the index. Then update and delete the document to confirm the sync function handles all write types correctly.

```
firebase deploy --only functions:syncToAlgolia
```

**Expected result:** The function deploys successfully. Creating a document in the products collection triggers indexing in Algolia within seconds.

## Complete code example

File: `functions/src/index.ts`

```typescript
// functions/src/index.ts
import { onDocumentWritten } from 'firebase-functions/v2/firestore'
import { defineSecret } from 'firebase-functions/params'
import algoliasearch from 'algoliasearch'

const ALGOLIA_APP_ID = defineSecret('ALGOLIA_APP_ID')
const ALGOLIA_ADMIN_KEY = defineSecret('ALGOLIA_ADMIN_KEY')
const ALGOLIA_INDEX_NAME = 'products'

export const syncToAlgolia = onDocumentWritten(
  {
    document: 'products/{productId}',
    secrets: [ALGOLIA_APP_ID, ALGOLIA_ADMIN_KEY]
  },
  async (event) => {
    const client = algoliasearch(
      ALGOLIA_APP_ID.value(),
      ALGOLIA_ADMIN_KEY.value()
    )
    const index = client.initIndex(ALGOLIA_INDEX_NAME)
    const { productId } = event.params

    // Handle deletion
    if (!event.data?.after.exists) {
      await index.deleteObject(productId)
      console.log(`Deleted ${productId} from Algolia`)
      return
    }

    // Handle create or update
    const data = event.data.after.data()
    await index.saveObject({
      objectID: productId,
      name: data?.name,
      description: data?.description,
      category: data?.category,
      price: data?.price,
      createdAt: data?.createdAt?.toMillis() ?? Date.now()
    })
    console.log(`Synced ${productId} to Algolia`)
  }
)
```

## Common mistakes

- **Using the Algolia Admin API Key on the client side, which gives anyone full write and delete access to your index** — undefined Fix: Use the Search-Only API Key for client-side queries. The Admin key must only be used in Cloud Functions or other server-side code.
- **Forgetting to set objectID when saving to Algolia, causing Algolia to generate random IDs that cannot be matched to Firestore documents** — undefined Fix: Always set objectID to the Firestore document ID. This allows update and delete operations to target the correct Algolia record.
- **Not handling the delete case in the onDocumentWritten trigger, leaving orphaned records in the Algolia index** — undefined Fix: Check if event.data.after.exists is false. If the document was deleted, call index.deleteObject with the document ID to remove it from Algolia.
- **Syncing all document fields to Algolia including sensitive data like user emails or internal IDs** — undefined Fix: Explicitly select which fields to index by destructuring only the fields you want. Never sync entire documents blindly with the spread operator in production.

## Best practices

- Store Algolia Admin API Key in Cloud Secret Manager using defineSecret, never in .env files or source code
- Use the algoliasearch/lite bundle on the client for a smaller bundle size
- Set searchableAttributes in Algolia to control which fields are searched and in what priority order
- Include the Firestore document ID as the Algolia objectID to maintain a 1:1 mapping for updates and deletes
- For initial backfill of existing data, write a one-time script that reads all Firestore documents and batch-indexes them to Algolia
- If your project involves complex search requirements across multiple collections, RapidDev can help architect the sync pipeline and search infrastructure
- Monitor Algolia usage in the dashboard to stay within your plan's record and operation limits

## Frequently asked questions

### Is there a Firebase Extension for Algolia?

Yes. The 'Search with Algolia' extension automates the sync between Firestore and Algolia without writing custom Cloud Functions. Install it from the Firebase Extensions Hub and configure the collection path, fields to sync, and Algolia credentials.

### How much does Algolia cost for Firebase projects?

Algolia offers a free tier with 10,000 search requests per month and 10,000 records. The paid plans start at $1 per 1,000 search requests. For most Firebase projects in early stages, the free tier is sufficient.

### Can I use Typesense instead of Algolia?

Yes. Typesense is an open-source alternative you can self-host. The sync pattern is identical: create a Cloud Function trigger that writes to the Typesense API on Firestore document changes. Typesense also has a Firebase Extension.

### How do I backfill existing Firestore data to Algolia?

Write a one-time Node.js script that reads all documents from your Firestore collection using the Admin SDK and batch-indexes them to Algolia using index.saveObjects(). After the backfill, the Cloud Function trigger handles ongoing syncs.

### Will the sync function slow down my Firestore writes?

No. Firestore triggers are asynchronous. The write to Firestore completes immediately and the Cloud Function runs in the background. Users do not experience any latency from the Algolia sync.

### How do I handle partial updates without overwriting the entire Algolia record?

Use index.partialUpdateObject() instead of saveObject() if you only want to update specific fields. However, for most use cases, saving the full object on each update is simpler and ensures consistency.

---

Source: https://www.rapidevelopers.com/firebase-tutorial/how-to-use-firebase-with-algolia
© RapidDev — https://www.rapidevelopers.com/firebase-tutorial/how-to-use-firebase-with-algolia
