PostgreSQL's 16-slot fast-path lock array can bottleneck heavily-indexed tables
PostgreSQL takes a weak AccessShareLock on a table and every one of its indexes each time it plans a query, even indexes the plan doesn't end up using. Through version 17, each backend can only record 16 such locks in a private fast-path array before overflowing into the shared lock table, which is guarded by 16 LWLock partitions that become contention points under heavy concurrent load.
GoKawiil's interpretation of the reporting above, not reported fact.
Tables with many secondary indexes can silently cross this 16-lock threshold, turning simple primary-key lookups into a source of CPU-heavy lock contention as query volume and core counts rise. It's a reminder that index counts have hidden concurrency costs beyond storage and write overhead, and that database internals like fast-path arrays impose real limits developers rarely think about until they hit scale.
- Every PostgreSQL query locks the table and all its indexes, not just the ones it uses.
- Each backend has only 16 fast-path slots for weak locks before falling back to the contention-prone shared lock table.
- Tables with more than ~15 indexes risk CPU-bound lock contention under high query rates, even on trivial queries.
Source: thebuild.com, 2026-09-14
Published there as: “Sixteen Locks Ought to Be Enough for Anybody”
Read the original report → The summary and analysis above are GoKawiil's own, written from reporting by the source above. Facts and quotes belong to the original publisher.