A cached batch of ids that lowers but does not close the gap risk.

Postgres sequences hand out numbers with a cache

A sequence answers one number at a time under a lock, so caching turns many small locked calls into occasional large jumps. That single decision — correctness through a short lock, speed through batching — explains every sequence surprise: gaps after restarts, interleaved ids under concurrency, missing numbers in audit-sensitive tables. None of it is a bug; all of it follows from treating the sequence as a fast unique-number dispenser rather than an odometer. ...

August 2, 2027 · 4 min · XB Field Notes
Allocated sequence values can leave gaps while a primary key separately enforces stored-row uniqueness.

A sequence allocates numbers independently of rollback

A PostgreSQL sequence allocates numbers independently of whether the caller’s transaction eventually commits. That makes ordinary identifier generation practical under concurrency, but it also makes gaps normal. A sequence number describes an allocation; it does not prove that a row exists, that a transaction committed, or that every smaller number has been used. ...

April 12, 2027 · 5 min · XB Field Notes