Web Development · Search
Adding Search to Your SaaS: Typesense vs Meilisearch vs Algolia in 2026
A hands-on comparison of Typesense, Meilisearch, and Algolia for production SaaS search in 2026 — covering self-hosting, performance, pricing, and real implementation patterns.
Anurag Verma
6 min read
Sponsored
Postgres full-text search gets you surprisingly far. tsvector, tsquery, trigram indexes, and pg_trgm can handle most simple search requirements without introducing a new service.
But at some point, users expect typo tolerance, faceted filtering, instant results, and relevance tuning that doesn’t require a PhD in IR theory. That’s when a dedicated search tool earns its place.
Three tools dominate in 2026 for teams that have graduated past Postgres FTS: Typesense, Meilisearch, and Algolia. Here is an honest assessment of when to use each.
The Short Version
Typesense: best performance, tightest self-hosting story, best pricing, harder edge cases in schema management.
Meilisearch: easiest to get running, good relevance out of the box, active development, solid self-hosting.
Algolia: most mature, best documentation, excellent SDKs, most expensive by an order of magnitude.
All three give you typo tolerance, faceted search, geosearch, and sub-10ms query latency at typical SaaS scales.
Typesense
Typesense is written in C++, distributed as a single binary, and designed to run on small hardware. A $10/month DigitalOcean droplet handles millions of documents.
The self-hosted setup is genuinely simple:
docker run -p 8108:8108 \
-v /data/typesense:/data \
typesense/typesense:0.27.0 \
--data-dir /data \
--api-key=your-secret-key \
--enable-cors
Or use their Typesense Cloud, which starts at $0.03/hour for a shared instance.
Define a collection (Typesense’s term for an index):
import Typesense from 'typesense'
const client = new Typesense.Client({
nodes: [{ host: 'localhost', port: 8108, protocol: 'http' }],
apiKey: process.env.TYPESENSE_API_KEY!,
connectionTimeoutSeconds: 2,
})
await client.collections().create({
name: 'articles',
fields: [
{ name: 'id', type: 'string' },
{ name: 'title', type: 'string' },
{ name: 'content', type: 'string' },
{ name: 'author', type: 'string', facet: true },
{ name: 'tags', type: 'string[]', facet: true },
{ name: 'published_at', type: 'int64' },
{ name: 'view_count', type: 'int32' },
],
default_sorting_field: 'published_at',
})
Search with typo tolerance and facets:
const results = await client.collections('articles').documents().search({
q: 'getting started typescript',
query_by: 'title,content',
facet_by: 'author,tags',
filter_by: 'published_at:>1700000000',
sort_by: '_text_match:desc,view_count:desc',
num_typos: 1,
per_page: 10,
})
Typesense’s weak point is schema evolution. Adding a new field to a collection requires re-indexing all documents (Typesense calls this creating a new collection and doing an alias swap). It’s manageable but needs to be part of your deployment plan.
Meilisearch
Meilisearch trades some of Typesense’s raw performance for a more forgiving developer experience. You can index documents without declaring a schema first — Meilisearch infers field types automatically.
Self-hosted setup:
docker run -p 7700:7700 \
-v /data/meili:/meili_data \
getmeili/meilisearch:v1.8 \
meilisearch --master-key=your-master-key
Indexing documents (no schema declaration required):
import { MeiliSearch } from 'meilisearch'
const meili = new MeiliSearch({
host: 'http://localhost:7700',
apiKey: process.env.MEILI_MASTER_KEY,
})
const index = meili.index('articles')
// Index documents - types are inferred
await index.addDocuments([
{
id: '1',
title: 'Getting Started with TypeScript',
content: 'TypeScript adds type safety to JavaScript...',
author: 'Jane Smith',
tags: ['typescript', 'javascript'],
published_at: 1700000000,
},
])
Configure searchable fields and facets separately:
await index.updateSettings({
searchableAttributes: ['title', 'content'],
filterableAttributes: ['author', 'tags', 'published_at'],
sortableAttributes: ['published_at', 'view_count'],
typoTolerance: {
enabled: true,
minWordSizeForTypos: { oneTypo: 5, twoTypos: 9 },
},
})
Search:
const results = await index.search('getting started typescript', {
filter: ['published_at > 1700000000'],
facets: ['author', 'tags'],
sort: ['published_at:desc'],
limit: 10,
})
Meilisearch Cloud starts at $30/month for a basic instance. The self-hosted version is fully open source under SSPL (same license as MongoDB — check the implications for your use case).
Algolia
Algolia is the cloud-only option. No self-hosting. In exchange, you get the most polished developer experience, the most battle-tested infrastructure, and the most thorough documentation.
The pricing is where most teams pause. Algolia’s free tier allows 10,000 search requests/month and 10,000 records. At any meaningful scale, costs run $0.50-$1.00+ per 1,000 requests, which adds up fast.
Where Algolia justifies the cost:
- Public-facing search where downtime is not acceptable
- Large catalogs with complex merchandising requirements (pinned results, synonyms, business rules)
- Teams where non-developers need to manage relevance tuning
- Products where search is a core feature, not a utility
Integration with algoliasearch:
import algoliasearch from 'algoliasearch'
const client = algoliasearch(
process.env.ALGOLIA_APP_ID!,
process.env.ALGOLIA_WRITE_API_KEY!
)
const index = client.initIndex('articles')
// Index objects (Algolia uses `objectID` as the primary key)
await index.saveObjects(articles.map(a => ({ ...a, objectID: a.id })))
// Configure index settings
await index.setSettings({
searchableAttributes: ['title', 'content'],
attributesForFaceting: ['author', 'tags'],
customRanking: ['desc(view_count)'],
})
Search from the client side using the search-only API key (safe to expose in browser code):
import { liteClient as algoliasearch } from 'algoliasearch/lite'
import InstantSearch from 'react-instantsearch'
const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
)
Algolia’s InstantSearch components handle pagination, facets, and highlighting with minimal code. This is the fastest path from zero to polished search UI.
Keeping Search in Sync
Regardless of which tool you pick, you need a strategy for keeping your search index in sync with your database.
Option 1: Write-through indexing
Index documents when you write them:
async function createArticle(data: ArticleInput) {
const article = await db.articles.create({ data })
// Index immediately after DB write
await searchClient.index(article)
return article
}
Simple, but the index update can fail after the DB write succeeds. Use a background job with retry for writes where eventual consistency is acceptable.
Option 2: Change Data Capture via webhooks or triggers
For Postgres, use logical replication or a trigger to emit events when rows change, then process those in a worker that updates the search index. More robust, slightly more infrastructure.
Option 3: Scheduled re-index
Re-index your entire collection every hour or every day. Workable at smaller scales, catches drift, but slow to reflect new content.
Most production setups combine options 1 and 3: write-through for immediacy, scheduled full re-index as a safety net.
Performance in Practice
At 1 million documents, all three tools return query results in under 10ms on modest hardware. At 100 million documents, differences appear.
Typesense’s C++ implementation handles high concurrency better on limited resources. Meilisearch’s Rust implementation is close. Algolia’s infrastructure scales horizontally without any of your involvement.
For a typical SaaS with under 10 million documents and under 1,000 queries per second, the performance difference between Typesense and Meilisearch is not meaningful. Pick based on the operational characteristics you care about.
A Concrete Recommendation by Team Type
Solo developer or early-stage product: Meilisearch self-hosted. Easy setup, generous terms, schema-free indexing means less upfront planning.
Team that already manages Kubernetes: Typesense. The self-hosted story is cleaner, performance headroom is better, and there’s a Typesense Cloud fallback if self-hosting becomes a burden.
E-commerce or marketplace with merchandising requirements: Algolia. The business user tools and InstantSearch components justify the cost.
Privacy-first or regulated product: Typesense or Meilisearch self-hosted. No data leaves your infrastructure.
Postgres FTS is still the right answer for many products. Before adding any search service, verify you actually need typo tolerance or faceted filtering. If you’re just doing text search against a few thousand rows, to_tsvector and a GIN index is enough.
Sponsored
More from this category
More from Web Development
Sponsored
The dispatch
Working notes from
the studio.
A short letter twice a month — what we shipped, what broke, and the AI tools earning their keep.
Discussion
Join the conversation.
Comments are powered by GitHub Discussions. Sign in with your GitHub account to leave a comment.
Sponsored