One outer statement-budget rectangle contains work, lock-wait, work and wait blocks; separate red brackets under the waits show a timer for each acquisition.

Locks wait politely when a transaction grabs them

A lock wait can be healthy coordination or an expensive queue. PostgreSQL’s lock_timeout lets an operation stop waiting, but it does not diagnose why the holder is slow or decide whether retrying is appropriate. Choose the timeout from the operation’s latency budget, and inspect the blocking transaction before increasing the limit or multiplying attempts. ...

February 16, 2028 · 5 min · XB Field Notes
A closed row changes to archived. Both states remain outside an open-only index, but changing the predicate column blocks HOT in the PostgreSQL 18 B-tree example.

Partial indexes and writes

A partial index filters rows, not columns. An index on id WHERE status = 'open' stores identifiers for open rows; status decides membership without becoming the search key. That distinction matters when estimating maintenance: a column need not appear in the stored key to affect an update’s cost. ...

February 15, 2028 · 5 min · XB Field Notes
An October predicate branches to September, October and November; the outer two partitions are crossed out and October remains.

Partition pruning skips whole partitions a query cannot need

Partition pruning excludes entire partitions that cannot contain matching rows. It is different from using an index to find rows within a remaining partition, and it is not a page-level cache trick. PostgreSQL can perform this exclusion while planning a query or later when parameter values become available during execution. ...

February 13, 2028 · 5 min · XB Field Notes
Staggered September and October intervals share an October-first boundary guide; filled starting endpoints and open ending endpoints show lower-inclusive, upper-exclusive ownership.

Table partitioning splits data by range or key

Range partitioning turns a boundary definition into a write-routing rule. PostgreSQL places a row in the partition whose bounds accept its key, whether the row arrives on time or months late. Correct boundaries, compatible timestamp types, and a plan for missing ranges matter before any query can benefit from pruning. ...

February 10, 2028 · 5 min · XB Field Notes
The same four scores produce positions 1,2,3,4, ranks 1,2,2,4 and dense ranks 1,2,2,3.

Window functions rank rows without collapsing groups

Ranking functions attach a position to each input row within a partition. They do not collapse a team, department, or customer into one aggregate row. The important choice is what a tie means: a unique position, a shared competition rank with gaps, or a shared rank counting distinct score groups. ...

February 8, 2028 · 5 min · XB Field Notes
A thousand-version bar passes the new threshold of 150 but stops short of the old threshold of 2050, with a cap-off-or-at-least-2050 prerequisite, illustrating eligibility rather than completed cleanup.

Autovacuum eligibility is separate from completion

A busy table produces obsolete versions at a rate its maintenance must accommodate. Lowering an autovacuum trigger can make that table eligible sooner, but eligibility is not completion. A worker must still reach the table, acquire the required locks, and finish enough useful cleanup before the backlog grows again. Measure that whole cycle instead of treating one configuration value as a throughput guarantee. ...

February 4, 2028 · 5 min · XB Field Notes
Order 1 continues referencing user id 1 while that user email changes. Identity generation, key constraints and authorization remain separate responsibilities.

A surrogate key keeps identity apart from meaning

A surrogate primary key separates row identity from a business value that can change. A customer’s email can be corrected while orders continue referencing the same customer identifier. This is useful when the business name is mutable or wide, but stability comes from schema and application policy. A generated number is not automatically immutable, secret, globally unique, or an authorization decision. ...

February 2, 2028 · 5 min · XB Field Notes
Session A holds a lock across a blocked connection to waiting session B; observer C points toward the waiting side.

A slower query needs both a plan and a wait check

A formerly fast query can become slow with the same data, statistics, and access plan. Another transaction may hold a lock, the storage cache may be colder, or the application may wait before PostgreSQL even receives the statement. Rechecking the plan is useful, but it belongs inside a broader comparison of where the elapsed time went. Begin by distinguishing time spent doing work from time spent waiting to do it. ...

January 31, 2028 · 5 min · XB Field Notes