Imagine running a big SELECT * on the order table while another process updates the same records concurrently. Your query completes displaying the original data, and the other sees successful data modification.This is Multi-Version Concurrency Control (MVCC), a technique where the database creates new copies of rows instead of overwriting them. Using MVCC, transactions get a consistent and isolated snapshot of the data, while ongoing updates happen simultaneously. Readers never block writers and writers never block readers because multiple versions coexist and visibility rules determine which one each transaction can see.There's a lot of complexity in how Postgres makes this work correctly. Here, we're gonna take a deep dive into how all this works in PostgreSQL. If database transactions are brand-new to you, you might find our Database Transactions article a helpful pre-requisite.Let's dig in!Transaction basicsTransactions rely on four guarantees known as ACID: atomicity, consistency, isolation, and durability.Those guarantees are easier to guarantee when transactions run one at a time. But how do we run thousands of transactions in parallel while safely coordinating access to the same data?MVCCEarly relational database management systems (RDBMS) like IBM System R solved this with read and write locks: hold a shared read lock to read, hold an exclusive write lock to modify. That kept data safe. It also meant readers blocked writers and writers blocked readers.PostgreSQL uses Multi-Version Concurrency Control instead. This allows it to maintain more than one version of a row and let each transaction read the version its snapshot allows. Multiple tuple versions can coexist on disk. Snapshot Isolation (SI) decides which version a transaction sees when it runs a query.PostgreSQL isn't the only database that uses MVCC, and each implements it in a different way. To understand how Postgres does, we must first understand how it stores rows in tuples.Tuples and visibilityA tuple is a single physical version of a row on disk. One logical row can exist as several tuples at once when PostgreSQL keeps older versions around for MVCC.For each tuple, PostgreSQL tracks which transaction created it and which transaction deleted it. Each transaction is identified by an unsigned 32-bit integer value called the transaction id (XID). When a tuple is updated, the old version is marked as deleted and a new tuple is created.For example:postgres=> CREATE TABLE mytable(id SERIAL PRIMARY KEY, name VARCHAR NOT NULL);