Skip to content
PostgreSQL 2026-07-02 11 min

PostgreSQL Indexing for Real-World Performance

When to use B-tree, GIN, partial and composite indexes — with query plans you can read.

By Mohammad Zayed

Overview

Indexing is the highest-leverage performance work in most apps. The trick is matching the index type to the query shape — and proving it with EXPLAIN ANALYZE.

B-tree

composite index
create index idx_orders_tenant_created
  on orders (tenant_id, created_at desc);

Composite order matters: equality columns first, then range/sort columns.

GIN

jsonb + array
create index idx_docs_tags on documents using gin (tags);

Use GIN for array and JSONB containment queries.

Partial

partial index
create index idx_open_jobs on jobs (created_at)
  where status = 'open';

Reading EXPLAIN

plan
explain analyze
select * from orders
where tenant_id = 't1'
order by created_at desc
limit 20;

Watch for Seq Scan on large tables — that's your signal to index.

FAQ

See the FAQ section above.

Frequently asked questions

Do more indexes always help?
No. Indexes speed reads but slow writes and consume storage. Add an index only when a real query benefits and you've read its plan.
When should I use a partial index?
When most queries filter on a constant predicate (e.g. status = 'open'). A partial index is smaller and faster.

Continue reading

Want help building this?

Book a free strategy call. We'll map your bottlenecks to the right systems and send a clear roadmap — even if we don't work together.

Chat on Telegram

Usually replies within minutes. Chat on Telegram: @northflowstudio

No obligation consultationFounder-led projectsInternational clientsFast responseSecure communication