Every SaaS team building search faces the same decision, and plenty make it in the wrong order. They reach for Elasticsearch because it's the canonical answer, or wire up Algolia before testing whether Postgres could carry the workload. Your first action: write down your ten most common real queries, including two with typos, and run them against your current database. Keep that list for the rest of this post.
I haven't shipped a dedicated search engine in any project described on this site, so this comparison comes from vendor and PostgreSQL documentation, rechecked on 10 October 2026. Numbers I couldn't verify on a primary page are left out. If your app already uses Postgres, "is our existing database enough?" is the first useful question.
When is Postgres full-text search enough for SaaS search?
Postgres full-text search is enough when your catalog is modest, queries are mostly exact keywords, and typo tolerance or instant faceting isn't something users judge you on.
The Supabase team benchmarked Postgres FTS against SQLite FTS5, Typesense, MeiliSearch and OpenSearch on a 32MB movie dataset. They concluded Postgres FTS is "quite close performance-wise" to the others for this basic case. In their numbers, a query for "love" returned 5,417 results in 19.09 ms, and "super hero" returned 34 in 3.13 ms. The same article found that only Typesense and MeiliSearch handled misspellings, and the Postgres query for "suprman" returned nothing. That is one small dataset, so treat it as a scope statement, not a guarantee for your data.
The implementation is small: a `tsvector` column, a GIN index and a query built with `websearch_to_tsquery`. The PostgreSQL 18 docs call GIN the preferred text search index type, and GIN is not lossy, unlike GiST. Good fits are internal admin search, ticket subjects, article titles and project names.
Where does it stop working?
The limits show up when the requirement list grows. These are the ones I'd watch:
- Typo tolerance. `pg_trgm`, documented in the Postgres docs, adds similarity matching and index support for LIKE and ILIKE, so `ILIKE '%query%'` can be indexed with a trigram index. It works, but it's another extension to tune.
- Ranking. The ranking docs warn that ranking can be expensive because it reads the `tsvector` of every matching document, which can be I/O bound.
- Facets with live counts, instant search on every keystroke, and ranking by click signals. You build these yourself with GROUP BY and custom expressions.
Two smaller details from the docs help you size the risk. The `%` operator in `pg_trgm` uses a configurable similarity threshold that defaults to 0.3, so fuzzy matching needs tuning against your own data. And the text search limitations page caps a `tsvector` at less than 1 megabyte, which matters only if you index very large documents.
If you run on Supabase + Stripe, the tsvector-plus-GIN route keeps B2B SaaS search inside a stack you already operate. The SQL is small; validating ranking, tenant filters and real user queries is the part that takes time. Start there and migrate when the gap appears in your support queue, not before.
Is Typesense better than Postgres FTS for customer-facing search?
Typesense is better when customers judge search quality directly, because typo tolerance, prefix search and faceting are built into the engine and its defaults are documented.
The Typesense search parameters default `num_typos` to 2 for every queried field and `prefix` to true, so typo-tolerant, as-you-type matching works without configuration. Field order in `query_by` sets weight unless you pass explicit `query_by_weights`, and `_text_match` breaks ties when you sort by other fields.
Typesense's own comparison page describes the design as instant search for data sets that fit in RAM. That's a vendor statement, and the practical consequence is worth checking: size memory for the index and growth, not only the raw document size.
For uptime, the high availability guide says Typesense uses Raft and needs at least 3 nodes to survive one node failure. Reads are served by whichever node gets them, and writes are forwarded to the leader. If a cluster loses quorum, it stops accepting reads and writes until someone intervenes, which is a real operational duty to plan for.
What about Meilisearch? It may be a good fit too, but a fair fourth-way comparison needs its current high-availability and hosting requirements checked separately. Test the same ten queries before you shortlist any engine.
What changes when search leaves Postgres?
A dedicated index is a copy of your product data, not the source of truth. Plan how creates, edits and deletes reach it; how you retry failed indexing jobs; and how you rebuild after a bug. Measure the delay between a database write and a searchable result. For permissions, index only fields users are allowed to discover, and treat tenant and role checks as mandatory at query time. If a user loses access, stale search results must not keep revealing titles or snippets while the index catches up. That operational work belongs in the migration estimate alongside search quality.
How much do Algolia and Typesense cost for SaaS search?
Algolia bills search requests and records, while Typesense is free to self-host and Typesense Cloud bills dedicated clusters hourly by RAM and CPU, so the gap grows with query volume.
The Algolia pricing page lists a Free plan with 10K search requests per month. Grow includes 10K requests and then charges $0.50 per additional 1K, plus $0.40 per additional 1K records above 100K. Grow Plus charges $1.75 per additional 1K requests. The same page lists 50K records on the Free plan. The enterprise tier is custom-priced with volume discounts and a listed 99.99% availability. The October 2, 2025 announcement introduced Grow Plus with AI synonyms, AI ranking, advanced personalization, query categorization and collections, and says Algolia powers 1.75 trillion searches a year.
| Item | Algolia Grow | Algolia Grow Plus | Typesense |
|---|---|---|---|
| Price per extra 1K searches | $0.50 | $1.75 | No per-search fee; you pay for infrastructure |
| Illustrative 5M searches/month | about $2,495 | about $8,733 | Depends on node size |
| Self-hosting | No (SaaS only) | No (SaaS only) | Yes |
| Typo tolerance and facets | Yes | Yes | Yes |
The illustrative row is my arithmetic on the listed rates: (5,000,000 minus 10,000 included) divided by 1,000, times the per-1K price, ignoring record charges. Typesense Cloud rates depend on the cluster you size, so I left a figure out. Get a quote for your own RAM and CPU.
Algolia earns its price when search is a conversion lever and someone on your team tunes ranking, such as an e-commerce catalog. A project management or clinic tool usually has no merchandising team. There, Typesense's infrastructure-based billing may fit better, but that is a judgment to test against your real query volume.
How do you isolate tenant data in multi-tenant search?
You isolate tenants by forcing a tenant filter on every query, either structurally in SQL or cryptographically through scoped keys in a dedicated engine.
In Postgres, every query carries a `WHERE tenant_id = $1` filter, and RLS policies can enforce it at the database level. With a dedicated engine you build isolation explicitly. Three patterns, in ascending operational cost (the multi-tenant SaaS tools list covers the wider shortlist):
- Shared collection with scoped keys. Generate a search-only parent key, then derive one key per tenant. The Typesense docs say scoped keys are an HMAC-SHA256 digest of embedded parameters, and embedded `filter_by` can't be overridden by the client. Never expose the main search key client-side. Algolia's secured API keys work the same way: generated on your backend, with filters users can't alter.
- Separate collection per tenant. Hard isolation, simpler mental model, more schema management as tenants multiply.
- Separate cluster per tenant. Reserved for contracts with strict isolation requirements, since cost scales with tenant count.
On Callidus, a React + Firebase + Stripe Connect clinic SaaS built solo between February and April 2026, the case study documents everything under `tenants/{tenantId}/…` in Firestore, with JWT claims carrying `tenantId` and `role` and Firestore rules gating access. It has 14 onboarded tenants per the case study. It isn't a Postgres product, so the FTS question doesn't apply there, but the isolation rule is identical: scope every query by tenant. BookBed is a Flutter + Firebase + Stripe property management product; the case study doesn't describe a search layer, so I make no search claim about it.
Which ranking signals are worth adding first?
Add recency, popularity and field weighting, in that order of effort. In Postgres, `setweight` labels parts of a document A to D (defaults 1.0 for A down to 0.1 for D) and `ts_rank` uses them. In Typesense, put the field you want weighted most first in `query_by` or pass `query_by_weights`, and combine `_text_match` with a numeric field such as a view count in `sort_by`. Facet queries on Postgres run as GROUP BY against the same database as your writes, which is a workload separation question before it's a capability gap.
Your next step: run `EXPLAIN ANALYZE` on your current search query, then run the typo queries from your list. If several return nothing useful, prototype Typesense with scoped keys on a copy of your data and compare the same list.




