The Postgres Guy

Blog

Postgres internals, performance, and operations — without the years of trial-and-error.

22 min read

Building a Concurrent Ledger in Postgres

You have a ledger table for all your customers' accounts. You want two transactions on the same account to serialize, but transactions on different accounts to run in parallel. This post describes a solution using an advisory lock keyed on the account id.

postgresqlsql developmenttransactions
7 min read

Autovacuum was running. Your table still bloated.

Autovacuum being enabled doesn't mean it's keeping up. The default threshold scales with table size, and the fix isn't the command you'd reach for first.

postgresqlautovacuumvacuum
5 min read

Why autovacuum ignores your biggest table

The default thresholds were sized for tables that don't exist anymore. Here's the math that actually scales — and the per-table overrides that fix it.

postgresqlautovacuumperformance tuning
5 min read

But It's a Simple Query — Why Is It So Slow?

Two WHERE clauses that look identical to you can look completely different to the PostgreSQL planner. A short tour of function volatility — IMMUTABLE, STABLE, VOLATILE — and why now() changes how your query gets planned.

postgresqlquery plannerperformance tuning
18:275 min read

How PostgreSQL Really Handles Connections

Every connection to PostgreSQL spawns a dedicated OS process. That isolation is a feature — until you have 500 of them sitting idle, eating RAM, and your app starts getting FATAL errors. Here's what's actually happening under the hood.

postgresqlconnection poolingpgbouncer
5 min read

Why your sort spilled to disk — and what to do about it

A misunderstood setting, a misread symptom, and the concurrency math nobody warns you about. The second piece in a series on PostgreSQL memory, this time on work_mem and why your sort spilled to disk.

postgresqlwork_memperformance tuning
6 min read

Continuous aggregates: the materialized view that refreshes itself

Your dashboard re-aggregates millions of rows on every page load. A plain materialized view goes stale and rebuilds the whole thing. TimescaleDB continuous aggregates fix both — incrementally — and most people set them up in a way that quietly recomputes the present every time. Here's how they actually work.

postgresqltimescaledbcontinuous aggregates
4 min read

Why adding more shared_buffers doesn't always help

The first piece in a series on PostgreSQL memory. Why the RAM that looks idle in htop is already working, why bigger shared_buffers stops helping past a point, and the one diagnostic that actually tells you whether you need more.

postgresqlshared_buffersperformance tuning

Page 1 of 3 · 27 posts