PostgreSQL's 16-Slot Lock Fast Path Is a Hidden Bottleneck for Over-Indexed Tables

Sixteen Locks Ought to Be Enough for Anybody

Every query in PostgreSQL takes an AccessShareLock on every index on a table, even ones it doesn't use. Through version 17, each backend has only 16 fast-path slots for these weak locks; overflow goes through the shared lock table and its 16 LWLocks, causing contention on trivial primary-key lookups. Prepared statements can cut locks from 22 to 2, and PostgreSQL 18 sizes the fast-path array from max_locks_per_transaction, giving 64 slots by default.

The disease is a table with 21 indexes.

More from this day

2026-09-17