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
| Function | What It Checks | Typical Use |
|---|---|---|
| attribute_exists(attr) | Attribute is present in the item | Prevent writing to nonexistent items |
| attribute_not_exists(attr) | Attribute is absent from the item | Prevent duplicate inserts |
| attribute_type(attr, type) | Attribute is a specific data type | Data type validation |
| begins_with(attr, substr) | Attribute value starts with a substring | Prefix checks on string keys |
| contains(attr, value) | String or set contains a value | Check tag membership |
| size(attr) | Returns the size of a string or set | Limit 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_existsto 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.
