The cost of every index
Each index makes INSERT, UPDATE (on indexed columns), and DELETE more expensive. Each index takes disk space and competes for cache. Each index has to be maintained by VACUUM. Indexes also constrain your write throughput. Adding indexes to "speed things up" without measuring is a great way to slow your writes by 5× while making no read query meaningfully faster.
The strategy in three rules
- Add indexes for queries you measure — not queries you imagine. EXPLAIN ANALYZE is the source of truth.
- Always index foreign keys — no exceptions for tables that ever have parent rows deleted.
- Periodically prune unused indexes —
pg_stat_user_indexes.idx_scan = 0over months means the index is dead weight.
The unused-index audit
PostgreSQL tracks how often each index has been used. After your application has been in production for a while, this catalog query reveals indexes nobody uses. Drop them after a sanity check.