Postgres ships five index types. Most apps only use one (B-tree, the default). Knowing the others unlocks 10-100x speedups on the right queries — and avoids creating useless indexes on the wrong ones.
B-tree — default workhorse
Equality and range queries on ordered data. Numbers, dates, strings, single-column or multi-column. ~99% of indexes you'll create. Default for primary keys, foreign keys, anything frequently filtered.
GIN — composite values
Indexing JSONB, arrays, full-text. Multiple keys per row (one row's array has many values, all indexed). Slow to update (good for read-heavy). Right answer for 'find all rows where tags contains X'.
BRIN — huge tables, correlated data
Stores summary per block range. Tiny (~1000x smaller than B-tree). Works when data is naturally ordered (time-series, append-only IDs). Bad if data is unordered. Useful for huge tables where B-tree is too big.