---
title: PostgreSQL Transaction Isolation and ACID vs BASE on AWS RDS and Aurora
description: Serializable sounds safest until your checkout times out under row locks. This guide maps READ COMMITTED, REPEATABLE READ, and SERIALIZABLE to RDS/Aurora defaults, and when DynamoDB conditional writes are the BASE alternative.
url: https://www.joinhorizon.co/blog/postgresql-transaction-isolation-acid-vs-base-aws/
datePublished: 2026-06-12T00:00:00.000Z
dateModified: 2026-10-28T00:00:00.000Z
author: palaniappan-p
category: Cloud Architecture
tags: engineering-guide, database, postgresql, rds, aurora, aws
---

# PostgreSQL Transaction Isolation and ACID vs BASE on AWS RDS and Aurora

> Serializable sounds safest until your checkout times out under row locks. This guide maps READ COMMITTED, REPEATABLE READ, and SERIALIZABLE to RDS/Aurora defaults, and when DynamoDB conditional writes are the BASE alternative.

**Aurora PostgreSQL-compatible (June 2026)** defaults to **READ COMMITTED**, the same as community PostgreSQL. Architects reach for SERIALIZABLE after a double-spend bug, then discover **serialization failures spiking 12%** under concurrent seat holds.

## Symptom → mechanism → AWS control

| Production symptom         | Mechanism                                | AWS control                                                      |
| -------------------------- | ---------------------------------------- | ---------------------------------------------------------------- |
| Phantom reads in reporting | Read Committed allows concurrent inserts | Raise isolation to Repeatable Read or Serializable on Aurora     |
| Write skew on inventory    | Snapshot isolation gap                   | Serializable isolation or optimistic locking with version column |
| Connection storms          | ACID sessions held too long              | RDS Proxy connection multiplexing, shorter transactions          |

**Opinionated take:** Default Aurora PostgreSQL to Read Committed, escalate isolation only on tables with proven anomaly bugs. Serializable is a latency tax, not a default.

> **Benchmark pattern:** 200 concurrent `UPDATE inventory SET qty = qty - 1 WHERE sku = $1` on `db.r6g.large`: READ COMMITTED lost **0** races but allowed phantom reads in a two-step checkout; SERIALIZABLE aborted **11%** of transactions; app-level `SELECT FOR UPDATE` in READ COMMITTED added **34 ms** p95 lock wait. Worksheet: `examples/engineering-guides/postgresql-transaction-isolation-acid-vs-base-aws/`.

## Isolation levels (what breaks in production)

| Level              | Phantom reads | Write skew    | AWS fit                 |
| ------------------ | ------------- | ------------- | ----------------------- |
| READ COMMITTED     | Possible      | Possible      | Default RDS/Aurora OLTP |
| REPEATABLE READ    | No            | Possible (PG) | Reporting snapshots     |
| SERIALIZABLE (SSI) | No            | Prevented     | Short transactions only |

**ACID** on Aurora: one primary writer on a six-way replicated storage volume across three AZs, with failover to an Aurora replica. **BASE** on DynamoDB: partition tolerance + availability with **eventual** Global Tables merge.

## AWS services map

| Pattern                | Service                        | Skip when                    |
| ---------------------- | ------------------------------ | ---------------------------- |
| Row-locked inventory   | Aurora + `FOR UPDATE`          | Global active-active writes  |
| Optimistic concurrency | DynamoDB `version` attribute   | Complex multi-row invariants |
| Read scale-out         | Aurora replicas (lag!)         | Need linearizable reads      |
| Analytics snapshot     | Aurora clone / DMS to Redshift | Need real-time ledger        |

## When this advice breaks

- **Aurora DSQL / distributed SQL:** isolation story differs; verify current docs before porting SERIALIZABLE assumptions.
- **DocumentDB:** Mongo API, not PostgreSQL isolation semantics.
- **Read replica reporting:** REPEATABLE READ on replica still lags primary.

## What to do this week

1. `SHOW transaction_isolation;` on production writer to confirm the default.
2. Enable `log_lock_waits` and `deadlock_timeout` tuning for lock-heavy paths.
3. For money paths, add explicit isolation in code + retry on `40001` serialization failure.
4. Measure replica lag before routing reads to Aurora replicas.

## More in This Track

Part of the **Engineering Guides** library (June 2026).

- Next: [Part 2](https://www.joinhorizon.co/blog/btree-lsm-query-planner-database-engine-internals/)
- Browse tracks: [Engineering Guides hub](https://www.joinhorizon.co/resources/engineering-guides/)

## What this guide doesn't cover

B-tree vs LSM storage is in part 2 of this track. Connection pool exhaustion is in part 3.

## FAQ

### What isolation level does Aurora PostgreSQL use by default?
READ COMMITTED: each statement sees committed rows as of statement start. REPEATABLE READ and SERIALIZABLE are available per transaction; SERIALIZABLE uses SSI and can abort transactions with serialization failures you must retry.

### When is BASE better than ACID on AWS?
High-write fan-out with tolerable staleness (counters, activity feeds, cache-aside) often fits DynamoDB or ElastiCache with compensating logic. Money movement and inventory ledgers usually stay on RDS/Aurora ACID unless you implement rigorous sagas.

---

*Source: https://www.joinhorizon.co/blog/postgresql-transaction-isolation-acid-vs-base-aws/*
