databaseEngineering
PostgreSQL — Core
The day-to-day database craft: indexing, reading EXPLAIN, transactions and isolation, locking, data modeling.
1 item
Links1
01NotesNote
Indexing — the highest-leverage skill
- Index every foreign key, and any column used in
WHERE,JOIN,ORDER BY, orGROUP BY. - Composite index column order matters. An index on
(a, b)serves queries filtering onaora + b, but notbalone. Put the most selective / most-equality-filtered column first. - Partial indexes for skewed predicates:
CREATE INDEX ... WHERE status = 'active'is smaller and faster when you almost always query active rows. - Covering indexes with
INCLUDElet an index-only scan return columns without touching the heap. - Indexes cost write throughput and disk. Don't index blindly — index for the queries you actually run.
Read EXPLAIN ANALYZE
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;
Seq Scanon a large table in a hot path = missing index (usually).- Watch for a big gap between estimated and actual rows → stale statistics; run
ANALYZE. Nested Loopover many rows is often a sign the planner chose wrong or an index is missing.
Transactions & isolation
- Default isolation is
READ COMMITTED. UseREPEATABLE READorSERIALIZABLEwhen you need consistent multi-statement reads, and be ready to retry on serialization failures. - Keep transactions short. A transaction held open across a slow external call holds locks and bloats the DB.
Locking & concurrency
SELECT ... FOR UPDATEto lock rows you're about to modify (e.g. decrementing inventory).SELECT ... FOR UPDATE SKIP LOCKEDis the classic pattern for a Postgres-backed job queue: each worker grabs the next unlocked row.- Beware deadlocks from inconsistent lock ordering — always acquire locks in the same order across code paths.
Data modeling
- Use the right types:
timestamptz(never naive timestamps),numericfor money (never float),uuidfor external IDs,jsonbfor flexible/semi-structured data. jsonbis powerful but not a schema replacement — index specific paths with expression or GIN indexes if you query into it.- Enforce invariants in the DB:
NOT NULL,CHECK,UNIQUE, FKs. The database is your last line of defense against bad data.