DynamoDB Conditional Writes

A conditional write tells DynamoDB to perform a write operation (Put, Update, or Delete) only if a specified condition is true at the moment of the write. If the condition is false, DynamoDB rejects the operation and returns an error — without modifying any data.

Why Conditional Writes Exist

Consider a seat booking system. Two users try to book the last available seat at the same moment. Without any protection, both writes could succeed, resulting in double booking. Conditional writes prevent this by enforcing a check at the database level before accepting the write.

The Double Booking Problem (Without Conditional Write)

Seat Status: "Available"

User A: Check status → "Available" ✓
User B: Check status → "Available" ✓

User A: Write "Status = Booked" → Success
User B: Write "Status = Booked" → Also succeeds (PROBLEM!)

Result: Two people booked the same seat.

The Same Scenario (With Conditional Write)

User A: Write "Status = Booked" IF Status = "Available" → Success
User B: Write "Status = Booked" IF Status = "Available" → FAILS (condition false)

Result: Only User A gets the seat. User B sees an error.

The condition check and the write happen atomically — as one unbreakable action. No other write can slip in between the check and the write.

Condition Expression Syntax

Conditional writes use a ConditionExpression parameter. The syntax is identical to Filter Expressions — attribute names, comparison operators, and placeholder values.

Example: Only Create If Item Does Not Exist

This prevents overwriting an existing user with a duplicate email.

PutItem:
{
  "TableName": "Users",
  "Item": {
    "Email":    { "S": "priya@example.com" },
    "Name":     { "S": "Priya Reddy" },
    "JoinDate": { "S": "2024-06-01" }
  },
  "ConditionExpression": "attribute_not_exists(Email)"
}

If a user with Email = priya@example.com already exists, DynamoDB rejects this write and throws a ConditionalCheckFailedException.

Example: Only Update If Item Exists

UpdateItem:
{
  "TableName": "Users",
  "Key": { "Email": { "S": "priya@example.com" } },
  "UpdateExpression": "SET City = :city",
  "ConditionExpression": "attribute_exists(Email)",
  "ExpressionAttributeValues": { ":city": { "S": "Hyderabad" } }
}

If the user does not exist yet, DynamoDB rejects the update instead of creating a partial item.

Example: Optimistic Locking with Version Numbers

Optimistic locking lets multiple users work on the same item without blocking each other. Each item has a Version number. When you update the item, you check that the version in the database matches what you read earlier. If someone else updated it first, the version will have changed, and your write will fail.

You read: { "ItemID": "I500", "Stock": 10, "Version": 3 }

Your UpdateItem:
  SET Stock = 9, Version = 4
  ConditionExpression: Version = :expectedVersion
  ExpressionAttributeValues: { ":expectedVersion": { "N": "3" } }

Case 1: No one else edited since you read → Version is still 3 → Write succeeds
Case 2: Someone else edited first → Version is now 4 → Write fails → You retry

Common Condition Functions

FunctionWhat It ChecksTypical Use
attribute_exists(attr)Attribute is present in the itemPrevent writing to nonexistent items
attribute_not_exists(attr)Attribute is absent from the itemPrevent duplicate inserts
attribute_type(attr, type)Attribute is a specific data typeData type validation
begins_with(attr, substr)Attribute value starts with a substringPrefix checks on string keys
contains(attr, value)String or set contains a valueCheck tag membership
size(attr)Returns the size of a string or setLimit list length before appending

Handling ConditionalCheckFailedException

When a condition fails, DynamoDB throws ConditionalCheckFailedException. Your application must handle this explicitly. The correct response depends on the business logic:

  • Duplicate prevention: Show the user an error ("Email already registered").
  • Optimistic locking: Re-read the latest item and retry the operation.
  • Booking conflict: Inform the user the seat is taken and offer alternatives.

Conditional Writes in Batch and Transaction Operations

Standard BatchWriteItem does not support condition expressions — it is a simple bulk write. For conditional writes on multiple items, use DynamoDB Transactions (TransactWriteItems), which is covered in detail in the Transactions topic.

Diagram: Seat Booking with Conditional Write

TABLE: Seats
┌──────────┬────────────┬──────────────┐
│ FlightID │ SeatNumber │ Status       │
├──────────┼────────────┼──────────────┤
│ AI505    │ 12A        │ Available    │
└──────────┴────────────┴──────────────┘

User A and User B both attempt to book seat 12A simultaneously:

User A → UpdateItem:
  SET Status = "Booked", BookedBy = "A"
  Condition: Status = "Available"
  → AWS processes this first → Condition TRUE → Write succeeds

User B → UpdateItem:
  SET Status = "Booked", BookedBy = "B"  
  Condition: Status = "Available"
  → AWS processes this second → Status is now "Booked" → Condition FALSE
  → ConditionalCheckFailedException → User B told seat is taken

Summary

  • Conditional writes execute a write only when a condition evaluates to true.
  • Use attribute_not_exists to prevent duplicate inserts.
  • Use version numbers with conditional writes to implement optimistic locking.
  • Failed conditions throw ConditionalCheckFailedException — handle this in your code.
  • The check and write are atomic — no other operation can interrupt between them.

Leave a Comment

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