What you'll learn
- Condition Expressions enforce rules before writing to DynamoDB.
- UpdateItem can create a new item, so also assert that the target key exists.
- Conditional checks occur server-side, preventing race conditions.
Section 01
Safe Legendary Catches
By adding a ConditionExpression to our UpdateItem call, we can tell DynamoDB: "Only assign ownership if this Lugia exists and has no owner." If someone else caught it a millisecond earlier, the condition fails and DynamoDB throws a ConditionalCheckFailedException.
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, UpdateCommand } from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient({ region: "ap-south-1" });
const docClient = DynamoDBDocumentClient.from(client);
await docClient.send(new UpdateCommand({
TableName: "LegendaryPokemon",
Key: { Name: "Lugia" },
UpdateExpression: "SET #own = :trainer",
ConditionExpression: "attribute_exists(#name) AND attribute_not_exists(#own)",
ExpressionAttributeNames: { "#name": "Name", "#own": "Owner" },
ExpressionAttributeValues: { ":trainer": "Ash" }
}));Ready · 9 steps · Orbi
This animation plays when you scroll to it. Press Play to start it now.
All steps as text
- Trainer Ash sends UpdateItem to the JohtoPokemon table with Name = "Lugia". No ConditionExpression: SET #own = :trainer
- DynamoDB hashes "Lugia" to 96f9f356, which routes the request to partition P2.
- P2 updates Lugia (Owner → Ash).
- This call consumed 1 WCU.
- DynamoDB responds with success: Ash caught Lugia.
- Trainer Gary sends UpdateItem to the JohtoPokemon table with Name = "Lugia". No ConditionExpression: SET #own = :trainer
- DynamoDB hashes "Lugia" to 96f9f356, which routes the request to partition P2.
- Trainer Gary's write to Lugia lands on P2 and silently replaces the other change.
- DynamoDB responds with success: both trainers were told they caught Lugia.
Practice
Your turn
Two trainers might throw a Master Ball at the same instant. Make the catch safe by only writing the
Owner if Lugia has no owner yet.Require
attribute_exists(#name), with #name mapped to Name and attribute_not_exists(#own). This prevents both duplicate ownership and a phantom item if Lugia's key does not exist.Tab inserts two spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the code.
Ctrl/⌘ Enter to run · simulated, no AWS callsSimulated — no AWS calls
Check
Check your understanding
Quick Quiz · one question, as many tries as you need.
What DynamoDB function checks if an attribute is missing before allowing a write?
Choose one answer.