Tutorials / Backend integrations / Set up Algolia search
📝 Written ● Intermediate Updated 2026-05-13

Set up Algolia search

Search-as-you-type with typo tolerance, faceting, and ranking — running globally on Algolia's network. Index your records via an API call; drop in the React/Vue/JS UI library. Sub-100ms queries from anywhere.

When to pick Algolia (and when not)

0
  • Pick Algolia when — you want polished search UI fast, type-ahead matters, you have ≤ ~1M records, search is user-facing and latency-critical.
  • Pick Meilisearch ↗ if you want open-source / self-hostable / Rust-based with similar DX.
  • Pick Typesense ↗ for another open-source option; cheaper at scale.
  • Pick Postgres full-text search (tsvector / tsquery) for simple needs already on your DB.
  • Pick OpenSearch ↗ / Elasticsearch for complex enterprise needs, log analytics, big data.

Algolia's sweet spot: indie SaaS that wants search to feel like Linear or Stripe's docs with a few hours of work.

Sign up + create an app

1

Sign up at algolia.com ↗. Build tier (free) covers 10K records + 10K requests/month — enough for a small app or doc site.

Dashboard shows your Application ID + four API keys:

  • Search-Only API Key — for browser/client. Read-only.
  • Admin API Key — for backend. Full control. Never ship to client.
  • Write API Key — for backend write operations.
  • Monitoring API Key — for usage stats.
ALGOLIA_APP_ID=ABCD1234
ALGOLIA_ADMIN_KEY=xxxxxxxxxxxxxxxxxxxxxxxx           # backend only
ALGOLIA_SEARCH_KEY=xxxxxxxxxxxxxxxxxxxxxxxx          # safe in browser
NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=xxxxxxxxxxxxxx        # ditto, for Next.js

Decide what to index

2

An Algolia "index" is a collection of records. A record is a JSON object — anything you'd want to surface in search.

For a blog: each post is a record. For e-commerce: each product. For a SaaS: maybe one index for documents, another for users, another for tags.

Each record needs an objectID (your unique identifier — your DB primary key works). Algolia auto-indexes every other top-level field.

{
  "objectID": "post-123",
  "title": "How to deploy to Vercel",
  "body": "First, install the CLI...",
  "author": "Jane",
  "tags": ["deploy", "vercel"],
  "published_at": 1714521600
}

Push records from your backend

3
npm install algoliasearch
import { algoliasearch } from "algoliasearch";

const client = algoliasearch(
  process.env.ALGOLIA_APP_ID,
  process.env.ALGOLIA_ADMIN_KEY      // admin key, BACKEND ONLY
);

// Save / replace a single record
await client.saveObject({
  indexName: "posts",
  body: {
    objectID: "post-123",
    title: "How to deploy to Vercel",
    body: "First, install the CLI...",
    tags: ["deploy", "vercel"],
  },
});

// Bulk replace (faster for initial import)
await client.saveObjects({
  indexName: "posts",
  objects: arrayOfPosts,
});

Run this on a schedule (every N minutes) or on every DB write that touches indexable content. JS API client docs ↗.

Configure your index settings

4

Dashboard → your index → Configuration. The two settings that matter most:

  • Searchable attributes — which fields participate in search, and in what priority order. title first, body second is typical. Docs ↗.
  • Ranking — Algolia's default ranking is "typo → geo → words → filters → proximity → attribute → exact → custom." For most apps, add a custom ranking attribute (e.g., popularity or published_at) to break ties. Ranking docs ↗.

Or via API:

await client.setSettings({
  indexName: "posts",
  indexSettings: {
    searchableAttributes: ["title", "body", "tags"],
    customRanking: ["desc(published_at)"],
  },
});

Search from the browser

5
import { algoliasearch } from "algoliasearch";

const client = algoliasearch(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY    // search-only key; safe in browser
);

const { hits } = await client.searchSingleIndex({
  indexName: "posts",
  searchParams: { query: "vercel deploy" },
});

Use the search-only key, not admin. The search key is restricted to read operations; safe to ship in your JS bundle.

Drop in the UI library

6

For instant search-as-you-type, don't roll your own. Algolia's InstantSearch library handles debouncing, faceting, pagination, and renders results.

React:

npm install algoliasearch react-instantsearch
import { liteClient } from "algoliasearch/lite";
import { InstantSearch, SearchBox, Hits } from "react-instantsearch";

const searchClient = liteClient(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY
);

export function Search() {
  return (
    <InstantSearch searchClient={searchClient} indexName="posts">
      <SearchBox />
      <Hits hitComponent={({ hit }) => <div>{hit.title}</div>} />
    </InstantSearch>
  );
}

Equivalents: Vue InstantSearch ↗, vanilla JS InstantSearch ↗, Docusaurus DocSearch ↗ (free for open-source docs).

Facets / filters

7

For "filter results by category / tag / price range," declare attributes as faceting:

await client.setSettings({
  indexName: "posts",
  indexSettings: {
    attributesForFaceting: ["tags", "author", "filterOnly(published)"],
  },
});

Then in InstantSearch:

import { RefinementList, HierarchicalMenu } from "react-instantsearch";

<RefinementList attribute="tags" />
<RefinementList attribute="author" />

The widgets render checkboxes and apply filters automatically. RefinementList docs ↗.

Sync your DB → Algolia automatically

8

You probably don't want to manually push every record. Two common patterns:

  • On every DB write — your DB write also calls saveObject. Simple, but doubles your latency.
  • Async via queue / background job — DB write fires an event; an Inngest function or queue worker syncs to Algolia. Decoupled; survives Algolia downtime.
  • Periodic full sync — every N minutes, fetch all changed records and bulk-save. Simplest; small staleness window.

For Postgres, Algolia ships a Postgres connector ↗ that handles syncing automatically (paid feature).

Common pitfalls

9
  • Records too large — Algolia has a 10 KB / 100 KB record limit (plan-dependent). Don't index full article bodies; index summaries + offset references.
  • Index everything = relevance suffers — searchable attributes should be a focused subset. Don't add author_bio if users won't search by it; it dilutes title/body matching.
  • Sync drift — DB and Algolia drift apart when sync fails. Add monitoring; reconcile counts periodically.
  • Forgetting to update on delete — when a record is deleted in your DB, you must also client.deleteObject() in Algolia. Easy to miss; surfaces as "I deleted that post but search still shows it."
Pricing climbs fast above the free tier. Algolia bills per search operation + per record. The free tier (10K records, 10K searches/month) is generous; Build plan starts at $0.40 per 1K extra records / $0.50 per 1K extra searches. A medium-traffic site can hit hundreds of dollars/month surprisingly fast. Algolia pricing ↗. Estimate carefully before scaling.

Self-hostable alternatives if pricing is a problem

10

If costs become uncomfortable:

  • Meilisearch ↗ — open-source, single-binary Rust app. Self-host on a $10 VPS for any volume. Cloud option also exists.
  • Typesense ↗ — similar story; open source + cloud.
  • Postgres FTS — for ≤ ~100K records and simple needs, tsvector + GIN index is free and good enough.

Both Meilisearch and Typesense ship Algolia-compatible APIs, so InstantSearch UI components plug right in with a different client.

Official references

What's next