Building DynamoDB Conditional Writes: Protecting Data Integrity
Learn how to use DynamoDB’s conditional expressions to prevent duplicate items, enforce uniqueness, and perform atomic updates — all through the AWS CLI.
In this tutorial, you’ll build a small user registration table, use condition expressions to ensure unique usernames, and safely update attributes without overwriting concurrent changes.
Step 1 – Create the Users Table
You’ll start with a simple table that uses Username as the partition key.
aws dynamodb create-table \
--table-name Users \
--attribute-definitions AttributeName=Username,AttributeType=S \
--key-schema AttributeName=Username,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Output:
{
"TableDescription": {
"TableName": "Users",
"TableStatus": "CREATING",
"BillingModeSummary": { "BillingMode": "PAY_PER_REQUEST" }
}
}
Check status:
aws dynamodb describe-table --table-name Users --query "Table.TableStatus"
Output:
"ACTIVE"
Step 2 – Insert a User (First Write)
Now add your first user record.
aws dynamodb put-item \
--table-name Users \
--item '{"Username":{"S":"alice"}, "Email":{"S":"alice@example.com"}, "Role":{"S":"member"}}'
Output:
{}
The empty JSON means success.
Step 3 – Prevent Duplicate Usernames
If you try to insert another record with the same key, DynamoDB would normally overwrite it.
To stop that, use a conditional expression requiring that the key not already exist.
aws dynamodb put-item \
--table-name Users \
--item '{"Username":{"S":"alice"}, "Email":{"S":"alice@duplicate.com"}, "Role":{"S":"member"}}' \
--condition-expression "attribute_not_exists(Username)"
Expected Output (Error):
{
"__type": "ConditionalCheckFailedException",
"message": "The conditional request failed"
}
That’s exactly what we want — the write was rejected because Username already exists.
This guarantees uniqueness at the database level, even under concurrent requests.
Step 4 – Safely Update Existing Items
Next, perform an atomic update.
You’ll update Alice’s role to admin, but only if her current role is still member.
aws dynamodb update-item \
--table-name Users \
--key '{"Username":{"S":"alice"}}' \
--update-expression "SET Role = :newrole" \
--condition-expression "Role = :expected" \
--expression-attribute-values '{":newrole":{"S":"admin"}, ":expected":{"S":"member"}}' \
--return-values ALL_NEW
Output:
{
"Attributes": {
"Email": {"S":"alice@example.com"},
"Role": {"S":"admin"},
"Username": {"S":"alice"}
}
}
The update succeeded because the condition was true.
If another process had already changed her role, the operation would fail safely.
Step 5 – Test Concurrent Update Failure
Simulate a race condition by changing the expected value.
aws dynamodb update-item \
--table-name Users \
--key '{"Username":{"S":"alice"}}' \
--update-expression "SET Role = :newrole" \
--condition-expression "Role = :expected" \
--expression-attribute-values '{":newrole":{"S":"owner"}, ":expected":{"S":"member"}}'
Expected Output:
{
"__type": "ConditionalCheckFailedException",
"message": "The conditional request failed"
}
This confirms atomicity — no blind overwrites occurred.
Step 6 – Clean Up
Delete your test table:
aws dynamodb delete-table --table-name Users
Confirm removal:
aws dynamodb list-tables
Output:
{"TableNames": []}
Wrap-Up
You’ve now built a fully atomic workflow in DynamoDB using condition expressions.
This technique protects against race conditions and duplicate data — especially critical in high-traffic APIs like registration systems or inventory counters.
Pro Tip #1 — Use attribute_not_exists() for Idempotency
Combine this check with API request IDs to ensure retried submissions never double-write data.
Pro Tip #2 — Batch Writes with Care
Conditional checks are per item, not per batch.
If you bulk-load data, handle ConditionalCheckFailedException gracefully and retry only the failed records.
DynamoDB Build Series
This concludes the DynamoDB Build Series — from queries to streams, lifecycle management, and now data integrity.
Together, these four posts form a concise, professional-grade foundation for working with DynamoDB in real-world systems.
Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.


Comments
Post a Comment