DynamoDB ConditionExpression for Concurrency Control
Problem
Incrementing a download counter — concurrent requests can exceed the max limit. The GET → check → UPDATE pattern is vulnerable to race conditions.
Solution
import { UpdateCommand } from '@aws-sdk/lib-dynamodb';
await docClient.send(new UpdateCommand({
TableName: 'tokens',
Key: { PK: `TOKEN#${token}`, SK: 'TOKEN' },
UpdateExpression: 'SET downloadCount = downloadCount + :inc',
ConditionExpression: 'downloadCount < :max',
ExpressionAttributeValues: {
':inc': 1,
':max': maxDownloads,
},
}));
// Throws ConditionalCheckFailedException if condition fails
Key Points
ConditionExpressionchecks the condition before executing the update. If the condition fails, the update doesn’t execute. This is atomic — race conditions are impossible.- “Read → check → write” in application code allows other requests to slip in between. Delegating the check to DynamoDB eliminates that gap.
- Catch
ConditionalCheckFailedExceptionto return “download limit exceeded” responses. This error is a normal part of business logic.