Advisory Locks in Postgres: A Simple Tool That Deserves Respect
Advisory locks are useful when the database cannot infer the thing you are protecting. They are also dangerous when session scope, pooling, and lock ordering are treated casually.
Notes for the problems that show up after launch: bad plans, awkward migrations, index debt, vacuum pressure, replica lag, and the small decisions that keep PostgreSQL, MySQL, MariaDB, and SQL Server easier to operate.
Find the queries dragging your Postgres down, read their plans, and fix them in order of impact.
Read the guide →Which indexes to add, which to drop, and how to spot redundant index debt before it costs you writes.
Read the guide →How autovacuum works, when it falls behind, and how to keep bloat from eating your storage and your buffer cache.
Read the guide →Sizing pools, PgBouncer modes, and how to stop idle-in-transaction sessions from exhausting max_connections.
Read the guide →Track lag, WAL throughput, and replication slots before they turn into stale reads or a full disk.
Read the guide →
Backups, restores, PITR, archive gaps, and recovery drills for PostgreSQL.
AWS RDS, Azure Database for PostgreSQL, Google Cloud SQL, AlloyDB, and managed PostgreSQL monitoring notes.
Connection storms, pool saturation, PgBouncer behavior, and max_connections pressure.
CPU, memory, disk, temp files, checkpoints, buffers, and workload pressure.
Index design, index debt, reindexing, constraint indexes, and evidence-driven DDL.
Lock waits, deadlocks, blocking chains, idle transactions, and transaction hygiene.
Galera clustering, InnoDB and Aria internals, replication, optimizer behavior, and MariaDB operations notes.
InnoDB internals, replication, locking, query performance, and MySQL operations notes.
HNSW, IVFFlat, recall, embedding search, and production RAG performance notes.
Replica lag, WAL growth, failover readiness, hot standby behavior, and replication slots.
Query plans, EXPLAIN ANALYZE, planner regressions, pagination, joins, and statistics.
Wait statistics, tempdb, Query Store, Always On availability groups, and SQL Server operations notes.
Autovacuum, dead tuples, bloat, wraparound, MVCC, freeze age, and visibility.
Advisory locks are useful when the database cannot infer the thing you are protecting. They are also dangerous when session scope, pooling, and lock ordering are treated casually.
Arrays are a Postgres feature that can simplify code and a feature that can lock you into bad design. Here is the rule I use to decide when to reach for them.
JSONB is great for things that genuinely vary per row. It is wrong for things that are stable. Most teams use it for both, and pay for it in queries that should have been simple.
WAL problems usually look like disk problems too late. Monitor generation rate, checkpoints, archiving, replication lag, and slot retention before pg_wal owns the incident.
Use NUMERIC when exactness is the product contract. Use DOUBLE PRECISION when measurement error is already part of the domain and speed matters more than decimal identity.
Postgres full-text search is great for the cases it covers and frustrating for the cases it doesn't. Knowing where the line is saves a year of trying to make it do what Elasticsearch does.
CITEXT is a good fit when a column is almost always compared case-insensitively. It is not a universal Unicode answer, and it is not free.
Range types model time windows, numeric ranges, and any "from-to" data. They support overlap queries natively and combine with EXCLUDE constraints to prevent invalid data.
Materialized views are excellent when stale-enough reads are worth a scheduled rebuild. They are painful when teams expect incremental freshness or forget the refresh lock model.
Rollup tables are pre-aggregated summaries of source data, kept up to date via triggers or scheduled jobs. They turn dashboard queries from seconds into milliseconds.