Postgres Full-Text Search

Built into Postgres. Free, no separate service, good enough for most apps.

VISIT POSTGRES FULL-TEXT SEARCH

Key takeaway: Already on Postgres? Start here and make the search service prove it is necessary. A tsvector column with a GIN index covers a surprising amount of application search with no extra infrastructure, no sync job and no second source of truth. Move to Typesense or Meilisearch at the point where search becomes a feature people tune, not before.

Quick facts

  • CategoryDatabase-native FTS
  • EnginePostgres
  • PricingOpen source
  • LicensePostgreSQL License
  • Created2008
  • GitHub starsclosed
  • Vector supportYes
  • Edge-readyNo

What it is

Postgres has had built-in full-text search since 2008 with tsvector / tsquery. GIN indexes, ranking with ts_rank, multi-language stemming via dictionaries. Pair with pg_trgm for fuzzy / typo tolerance and pgvector for hybrid lexical+vector. Not as fast as dedicated engines but sufficient for most apps.

Best for

  • Apps already on Postgres where adding a search service is overhead
  • Mid-scale workloads (under ~10M rows) where Postgres performance suffices
  • Hybrid lexical + vector search via pg_trgm + pgvector + tsvector together
  • Cost-conscious teams that want zero additional infrastructure

When not to pick it

Skip Postgres FTS for genuine search-product workloads (e-commerce search, content search at scale). Skip if you need typo tolerance comparable to Algolia / Meilisearch.

My take

Postgres FTS is underrated. For most apps with Postgres in the stack, it is a fine default. Graduate to Typesense / Meilisearch when search becomes a real product feature rather than a side concern.

The pattern that actually holds up

The setup worth copying is a stored generated column: a tsvector built from your text fields with setweight applied per field so a title match outranks a body match, backed by a GIN index, queried with websearch_to_tsquery so user input containing quotes and negation parses without you writing a parser. Rank with ts_rank_cd rather than ts_rank when phrase proximity matters. Add pg_trgm with its own GIN index for fuzzy matching on names and short fields, which is how you get something resembling typo tolerance. For semantic retrieval, pgvector lives in the same table, and you can combine the lexical score with vector distance in a single query using reciprocal rank fusion, no second system involved. On Supabase all of this is available without leaving the project you already have, which is precisely why so many builds never need a search service.

The three failure modes, and a cheap exit

Three things push you off Postgres full-text search. Relevance ceiling first: ts_rank understands term frequency and position, not click behaviour, business rules or field boosting beyond four weight classes, so merchandising requests eventually exceed it. Second, a GIN index on a write-heavy table adds real write amplification, and its pending-list behaviour makes update latency lumpy under load. Third, and usually the actual trigger, search queries and transactional queries compete for the same buffer cache and the same connection pool, so a slow search becomes a slow checkout. The exit is cheap if you plan for it. Keep Postgres as the source of truth and push a denormalised projection into Typesense or Meilisearch through logical replication or an outbox table. None of the modelling work is wasted, you simply stop serving queries from the primary.

Frequently asked questions

Is Postgres full-text search good enough for production?

For most application search, yes. Filtering a few million rows of user-generated content, documents or listings is well within what a GIN-indexed tsvector handles. It stops being good enough when search becomes a product surface people tune for conversion, or when search traffic starts competing with transactional queries on the same database.

Does Postgres full-text search handle typos?

Not on its own. tsvector matching is exact after stemming, so a misspelled query returns nothing. The usual fix is pg_trgm, which adds trigram similarity and works well on names and short fields, with a similarity threshold you tune. It is workable, but it is not the typo tolerance Algolia or Meilisearch give you for free.

Postgres FTS or Elasticsearch?

Postgres unless you have a concrete reason not to. Elasticsearch earns its place at large scale, with complex aggregations, or when search shares a cluster with log analytics. If the question is whether to add a JVM cluster to an app that already has a healthy Postgres, the answer is usually no, and Typesense is the lighter middle step.

Links

Compare Postgres Full-Text Search side-by-side

Similar tools you should also consider

If Postgres Full-Text Search is your pick, the next conversation is short

The 30-min call is where your search choice becomes a real architecture, a relevance-tuning plan, and a price range you can take to your stakeholders.