ACID Transactions Explained: Database Guarantees
ACID — atomicity, consistency, isolation, durability — defines the guarantees a database transaction makes so concurrent, failure-prone operations stay correct.
ACID is an acronym describing four guarantees a database transaction makes: atomicity, consistency, isolation, and durability. Together they define what it means for a transaction to be safe — that a group of operations either all happen or none do, that the database never ends up in a broken state, that concurrent transactions don’t corrupt each other’s results, and that a completed transaction survives a crash. Most relational databases are built around these guarantees by default; understanding them is what makes it possible to reason about what a database will and won’t protect you from.
Atomicity: all or nothing
A transaction groups multiple operations into a single unit that either fully commits or fully rolls back — there’s no partial state where some operations succeeded and others didn’t. The textbook example is a bank transfer: debiting one account and crediting another must happen together. If the debit succeeds but a crash happens before the credit, atomicity guarantees the entire transaction rolls back, leaving both accounts as if nothing happened, rather than money disappearing from the system.
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
If anything fails between BEGIN and COMMIT, the database rolls back both statements together.
Consistency: valid states only
Consistency means a transaction can only move the database from one valid state to another, respecting all defined constraints — foreign keys, unique constraints, check constraints, and any application-level invariants enforced at the database layer. A transaction that would violate a constraint (say, inserting a row that references a nonexistent foreign key) is rejected rather than partially applied. This is closely tied to database normalization, since a well-normalized schema with the right constraints is what gives the database something concrete to enforce consistency against.
Isolation: concurrent transactions don’t interfere
Isolation controls what one in-progress transaction can see of another transaction’s uncommitted changes. Without isolation, two transactions running at the same time could read each other’s half-finished work and produce corrupted results — a class of bug generally called a race condition when it shows up in concurrent systems more broadly.
Databases offer isolation levels that trade consistency guarantees against performance, since stronger isolation generally means more locking or more work resolving conflicts:
| Isolation level | Prevents |
|---|---|
| Read uncommitted | Nothing — dirty reads possible |
| Read committed | Dirty reads |
| Repeatable read | Dirty reads, non-repeatable reads |
| Serializable | Dirty reads, non-repeatable reads, phantom reads |
Serializable is the strongest level — it behaves as if every transaction ran one at a time, in some order, even though they actually ran concurrently. It’s also the most expensive, which is why most applications default to read committed or repeatable read and only reach for serializable when correctness genuinely requires it.
Durability: committed means committed
Once a transaction commits, its changes must survive a crash — a power loss or process kill immediately after commit shouldn’t lose that data. Databases achieve this by writing changes to a durable write-ahead log before acknowledging the commit, so recovery after a crash can replay the log and reconstruct any committed state that hadn’t yet been flushed to the main data files.
ACID vs BASE
ACID is the traditional model for relational databases like PostgreSQL. Many NoSQL and distributed systems instead favor BASE — Basically Available, Soft state, Eventually consistent — trading strict consistency for availability and horizontal scalability. This isn’t a strict downgrade; it’s a different point on the tradeoff space described by the CAP theorem, which formalizes why a distributed system can’t have full consistency, availability, and partition tolerance simultaneously.
| ACID | BASE | |
|---|---|---|
| Consistency | Strong, immediate | Eventual |
| Typical systems | Relational databases | Many NoSQL and distributed systems |
| Availability under partition | May sacrifice availability for consistency | Favors availability |
| Best for | Financial transactions, anything requiring strict correctness | High-scale systems where brief staleness is acceptable |
This is also why the choice between SQL and NoSQL databases often comes down to whether an application needs ACID’s strict guarantees or can tolerate BASE’s eventual consistency in exchange for easier horizontal scaling. Distributed SQL databases increasingly try to offer both, and database sharding and replication strategies both have to grapple with how much ACID compliance they can preserve once data is spread across multiple nodes.
Why this matters even if you never write raw SQL
Most application developers interact with ACID guarantees indirectly, through an ORM or query builder, but the guarantees still apply underneath. Knowing that a multi-step operation needs to be wrapped in an explicit transaction — rather than issued as several independent statements — is often the difference between an application that stays correct under concurrent load and one that silently corrupts data the first time two requests race each other.
The takeaway
ACID — atomicity, consistency, isolation, and durability — is the set of guarantees that make database transactions safe to build correctness on: operations complete fully or not at all, constraints are always respected, concurrent transactions don’t see each other’s half-finished work, and committed data survives a crash. Relational databases provide these by default; understanding the tradeoffs, especially around isolation levels and the ACID-versus-BASE split in distributed systems, is what lets you choose the right guarantees for a given workload instead of assuming the strongest option is always free.
Tagged
Keep reading
The Lycoris Team · · 5 min read What Is a Stored Procedure? SQL Logic in the Database
A stored procedure is precompiled SQL saved inside the database and invoked by name, cutting network round trips and centralizing business logic.
The Lycoris Team · · 5 min read What Is a Database Trigger?
A database trigger is a procedure that runs automatically on an insert, update, or delete — enforcing rules the application layer can't guarantee.
The Lycoris Team · · 4 min read Primary Key vs Foreign Key vs Unique Constraint
Primary keys identify a row, foreign keys link one table to another, and unique constraints just prevent duplicates. How the three differ in SQL.