The Postgres index that did nothing
Spent an hour last week wondering why a GIN index on a jsonb column was being ignored. The query used data->>'status' = 'active', the index was there, EXPLAIN kept showing a sequential scan.
The problem: a default GIN index on jsonb supports the containment operators (@>, ?, ?|, ?&), not the arrow-then-equals pattern I was writing. My query never touched an operator the index could answer.
Two fixes. Rewrite the query to use containment:
SELECT * FROM events WHERE data @> '{"status": "active"}';
Or, if you really want ->>, build an expression index on exactly that path:
CREATE INDEX ON events ((data->>'status'));
The lesson that stuck: an index is not a general promise about a column. It answers a specific set of operators. If the planner ignores your index, the first question is not “is the index missing” but “does this index actually cover the operator I wrote.” EXPLAIN tells you the truth; the schema only tells you what you hoped.