lockinglisted
Install: claude install-skill matejformanek/postgres-claude
# Locking — operational checklist
Companion to `knowledge/idioms/locking-overview.md`. Use this when you are about to **write code that touches shared memory** in `src/backend/`. Stop and read the overview first if you have not internalized the six-layer taxonomy (atomics → spinlocks → LWLocks → heavyweight → predicate → row).
## 0. Triage — is shared state actually involved?
Touching any of these means yes:
- A struct in `*Shmem*` allocation, anything reachable from `MainLWLockArray`, anything in `BufferDesc`/`PGPROC`/SLRU/`procArray`.
- Files on disk (pages flushed need to follow WAL-before-data).
- A relation, tuple, transaction id, or advisory key — these need heavyweight locks.
If everything you touch is on the backend's own stack/heap/`MemoryContext`, you don't need a lock at all. Per-backend `MemoryContext`s are *not* shared.
## 1. Decision tree
```
What are you protecting?
│
├─ A user-visible object (table / row / xact / advisory key)?
│ → Heavyweight lock via LockAcquire(LOCKTAG_*, mode, ...).
│ Pick the *weakest* mode in the conflict matrix that still excludes the bad
│ concurrency. See knowledge/idioms/locking-overview.md §1.4.
│
├─ A read in a serializable transaction that needs to be "remembered" so
│ later writes can detect rw-conflict?
│ → PredicateLockTuple/Page/Relation (only meaningful at SERIALIZABLE).
│
├─ A single word (counter, flag, packed state) on the hot path, where the
│ whole update fits in one CAS / fetch-and-add?
│ → pg_atomic_*.