DynamoDB Transactions

A transaction is a group of operations that either all succeed or all fail together. DynamoDB supports ACID transactions — meaning operations across multiple items or even multiple tables happen atomically, consistently, in isolation, and durably.

Why Transactions Are Needed

Many real-world operations involve multiple database changes that must stay in sync. If one step fails, all other steps must be rolled back — otherwise your data ends up in an inconsistent state.

Classic Example: Bank Transfer

Transfer ₹5,000 from Account A to Account B

Step 1: Deduct ₹5,000 from Account A
Step 2: Add ₹5,000 to Account B

What if Step 1 succeeds but Step 2 fails (network error)?
→ ₹5,000 disappears from Account A but never arrives in Account B
→ Money is lost from the system

With a transaction:
→ Both steps succeed or both fail
→ If Step 2 fails, Step 1 is rolled back automatically
→ No money is ever lost

DynamoDB ACID Guarantees

PropertyWhat It Means in DynamoDB
AtomicityAll operations in the transaction succeed, or none do
ConsistencyData remains valid before and after the transaction
IsolationOther operations cannot see partially completed transactions
DurabilityCommitted transactions persist even if the system crashes

Transaction API Calls

DynamoDB provides two transaction API calls:

  • TransactWriteItems — performs writes (Put, Update, Delete, ConditionCheck) atomically
  • TransactGetItems — performs reads atomically, returning a consistent snapshot

TransactWriteItems

Combines up to 100 operations across up to 100 items. Items can be in the same table or different tables. All operations either commit together or none of them apply.

Supported Actions in TransactWriteItems

  • Put — Insert or replace an item
  • Update — Modify attributes of an item
  • Delete — Remove an item
  • ConditionCheck — Check a condition on an item without modifying it; causes the whole transaction to fail if the condition is false

Example: Order Placement Transaction

When a customer places an order, three things must happen atomically: the order must be created, the product's inventory must decrease, and the user's order count must increase.

TransactWriteItems:
[
  {
    Put: {
      TableName: "Orders",
      Item: {
        OrderID: "ORD999",
        UserID: "U001",
        ProductID: "P100",
        Status: "Confirmed"
      },
      ConditionExpression: "attribute_not_exists(OrderID)"
    }
  },
  {
    Update: {
      TableName: "Products",
      Key: { ProductID: "P100" },
      UpdateExpression: "SET Stock = Stock - :qty",
      ConditionExpression: "Stock >= :qty",
      ExpressionAttributeValues: { ":qty": { "N": "1" } }
    }
  },
  {
    Update: {
      TableName: "Users",
      Key: { UserID: "U001" },
      UpdateExpression: "ADD OrderCount :inc",
      ExpressionAttributeValues: { ":inc": { "N": "1" } }
    }
  }
]

If the product is out of stock (condition on Stock fails), the entire transaction fails. The order is not created, the stock is not decremented, and the order count is not incremented. The database stays consistent.

TransactGetItems

Reads up to 100 items from one or more tables in a single, consistent snapshot. All items are read at the same point in time — no item reflects a change that was committed after the transaction started.

TransactGetItems:
[
  { Get: { TableName: "Accounts", Key: { AccountID: "A001" } } },
  { Get: { TableName: "Accounts", Key: { AccountID: "A002" } } }
]

Result: Both account balances reflect the same moment in time
No partial updates visible — true consistent read

Transaction Costs

Transactions cost exactly twice the normal operation cost:

  • Each write in a transaction costs 2 WCUs instead of 1
  • Each read in a transaction costs 2 RCUs instead of 1

The extra cost covers the two-phase commit protocol DynamoDB uses internally to guarantee atomicity.

Transaction Conflict Detection

If two transactions try to modify the same item at the same time, one of them gets a TransactionConflictException. Your application must catch this error and retry the transaction. DynamoDB does not automatically retry conflicting transactions.

Transaction X: Update item I100 (starts at T=0, commits at T=50ms)
Transaction Y: Update item I100 (starts at T=10ms)

At T=10ms, DynamoDB detects that I100 is locked by Transaction X
→ Transaction Y fails with TransactionConflictException
→ Your code retries Transaction Y after Transaction X commits

Idempotent Transactions with Client Token

Network failures can cause uncertainty — did the transaction succeed before the connection dropped? DynamoDB supports a Client Request Token in TransactWriteItems. If you retry the same request with the same token within 10 minutes, DynamoDB returns the original result instead of executing the transaction again. This prevents accidental duplicate transactions on retry.

First attempt:  ClientRequestToken = "token-abc" → Transaction commits
Network drops.  Did it succeed?
Second attempt: ClientRequestToken = "token-abc" → DynamoDB says "already done" ✓
No duplicate order, no duplicate stock decrement

Transaction Limits

LimitValue
Max operations per transaction100
Max total data per transaction4 MB
Tables in one TransactWriteItemsMultiple (across tables allowed)
Cost vs single operations2× the WCU or RCU cost

When to Use Transactions

  • Financial operations where multiple accounts must update together
  • Order placement that requires simultaneous stock reduction
  • Game state updates where multiple records must change atomically
  • Any operation where partial success is worse than total failure

When Not to Use Transactions

Transactions add cost and latency. Avoid them for single-item updates, situations where eventual consistency is acceptable, or high-volume write paths where the 2× cost would be prohibitive. Use conditional writes (single-item transactions) instead wherever possible.

Leave a Comment

Your email address will not be published. Required fields are marked *