Building DynamoDB Conditional Writes: Protecting Data Integrity

 

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

Popular posts from this blog

The New ChatGPT Reason Feature: What It Is and Why You Should Use It

Raspberry Pi Connect vs. RealVNC: A Comprehensive Comparison

Insight: The Great Minimal OS Showdown—DietPi vs Raspberry Pi OS Lite