Every Postgres app I've worked on runs at READ COMMITTED. It's the default. It's what your ORM opens transactions with unless you tell it otherwise. And it's silently allowing bugs you'd assume it prevents.

We tend to write database code with a vague sense that the transaction is "protecting" us — that once we wrapped a read and a write in BEGIN / COMMIT, the database would handle the concurrency. Most of the time it does. Right up until two requests hit the same row within the same few milliseconds.

Let's look at what READ COMMITTED actually promises. And what it doesn't.

What READ COMMITTED actually does

READ COMMITTED is one of four isolation levels in the SQL standard. It's Postgres's default. It's also the default in SQL Server and Oracle. MySQL InnoDB defaults to REPEATABLE READ, which is a slightly different story.