A named identifier the application locks, isolated from table-level locking.

Postgres advisory locks are named, app-level locks

An advisory lock lets an application coordinate work using an identifier that need not correspond to a table row. For example, workers can agree that only one connection may refresh a particular report at a time. PostgreSQL manages ownership and contention, while the application defines what the identifier means and which work requires it. ...

November 24, 2027 · 4 min · XB Field Notes
Several writes committed together or rolled back as one.

Transactions make atomic commits

A transaction lets related database changes commit together or be discarded together. Debiting an account, crediting another, and recording a ledger entry belong to the same decision when the operation requires all three. PostgreSQL provides that boundary through BEGIN, COMMIT, and ROLLBACK. The application must still place the correct statements inside it: atomic execution does not discover a forgotten credit or invent a missing business check. ...

May 12, 2027 · 5 min · XB Field Notes
A concurrency signal telling a transaction to start over.

A transaction can fail and leave you to retry

A competing update does not automatically make a PostgreSQL transaction fail. The outcome depends on isolation, statement behavior, and the state another transaction commits. Treating every collision as the same retryable event can conceal invalid input or repeat a decision made from stale data. The useful boundary is a complete application operation whose reads and writes can be attempted again. ...

February 1, 2027 · 4 min · XB Field Notes
A stable lock file coordinates writers even when the data pathname changes its inode.

File locks protect a shared protocol and a specific object

A file lock coordinates participants that agree on what to lock, when to acquire it, and which operations belong inside the critical section. Linux offers several lock interfaces with different ownership and release rules. Choosing a filename and calling something named lock is insufficient: the protocol must identify the underlying object, the lock family, and the lifetime of every reference involved. ...

December 5, 2026 · 5 min · XB Field Notes
A transaction that aborts and then starts over within a limited loop.

A bounded retry gives a transaction another chance

A retry can recover a transaction rejected because of concurrent work. It cannot guarantee success, and it does not automatically make external effects idempotent. The retry unit should include every database read and application decision that determined the writes. Reusing an amount calculated from the first attempt’s snapshot can defeat the purpose of starting a fresh transaction. ...

November 9, 2026 · 5 min · XB Field Notes
Two writers contending for one record and being allowed one at a time.

Locks and leases tame concurrent writers

A single writer is easy; multiple writers are where bugs live. Locks and leases are the two classic answers, and telling them apart decides whether your system can recover from a failed holder. Lock: a right you hold until you let go A lock grants exclusive write access and stays held until the owner releases it. That is simple and fast inside one process, but it has a hard failure mode in distributed systems: a holder that crashes or stalls never runs the unlock, so every waiter blocks forever. There is no timeout in the lock itself, so ‘release on failure’ must be supplied externally, and without it a single dead node takes the resource offline. A lock answers ‘who may write?’, but it cannot answer ‘how long?’. ...

October 4, 2026 · 6 min · XB Field Notes
Two transactions each holding a lock and waiting on the other until one is aborted.

Deadlocks happen when two writers wait on each other

A deadlock requires a cycle of incompatible waits. If one transaction holds a row while another waits, the holder can still finish and release it. If both hold a resource the other needs, neither can complete that path. PostgreSQL detects the cycle and aborts one transaction, allowing the other to continue. The application must distinguish that rejection from an ordinary slow wait. ...

August 11, 2026 · 4 min · XB Field Notes
A transaction reading an older snapshot while a writer creates a new version in parallel.

MVCC selects row versions through visibility rules

Multi-version concurrency control lets PostgreSQL keep different row versions and decide which ones a query may see. An ordinary reader can continue seeing an older committed version while another transaction writes a newer one. This reduces conflicts between reading and writing, but does not give every transaction one permanently frozen view. Snapshot lifetime depends on isolation, and a transaction can see its own earlier changes even when other transactions cannot. ...

August 8, 2026 · 4 min · XB Field Notes