Full-Text Search in PostgreSQL

A
Author
24 May, 2026 1 min read 1.29K views

For many apps, PostgreSQL's built-in full-text search is good enough to skip running a separate search engine. It handles stemming ("running" matches "run"), ranking and boolean queries.

Core concepts

SELECT to_tsvector('english', 'The runners were running quickly');
-- 'quick':5 'run':4 'runner':2

SELECT to_tsvector('english', 'Running tips for beginners') @@ websearch_to_tsquery('english', 'run beginner');
-- true

websearch_to_tsquery accepts search-box syntax: quotes for phrases, -word to exclude, or for alternatives.

A searchable table

ALTER TABLE articles ADD COLUMN search tsvector
  GENERATED ALWAYS AS (
    setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
    setweight(to_tsvector('english', coalesce(summary, '')), 'B') ||
    setweight(to_tsvector('english', coalesce(body, '')), 'C')
  ) STORED;

CREATE INDEX articles_search_idx ON articles USING gin (search);

Weights make title matches rank above body matches.

Search with ranking and snippets

SELECT id, title,
       ts_rank(search, q) AS rank,
       ts_headline('english', body, q, 'MaxWords=30, MinWords=10') AS snippet
FROM articles, websearch_to_tsquery('english', $1) q
WHERE search @@ q
ORDER BY rank DESC
LIMIT 20;

ts_headline is relatively slow; run it only on the final page of results (as here, after LIMIT).

Typos and partial words

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX articles_title_trgm_idx ON articles USING gin (title gin_trgm_ops);

SELECT title FROM articles
WHERE title % 'postgress'                 -- similar enough
ORDER BY similarity(title, 'postgress') DESC
LIMIT 5;

Trigram search is great for autocomplete and "did you mean" on short fields like names and titles.

When to reach for a dedicated engine

  • Very large corpora with heavy search traffic.
  • Advanced relevance tuning, faceting at scale, many languages.
  • Even then, keeping Postgres as the source of truth and syncing to the search engine is the usual design.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.