How to prevent a DynamoDB item being overwritten if an entry already exists
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
By default, DynamoDB treats PutItem as an upsert. If another item already exists with the same primary key, the new write replaces it.
To make the operation behave like "insert only if missing", add a condition to the write itself. That keeps the check atomic and prevents two concurrent requests from overwriting each other.
Use ConditionExpression with PutItem
The standard solution is attribute_not_exists. DynamoDB evaluates the condition on the server and only performs the write when the key does not already exist. That means you do not need a separate existence check in application code.
If an item with the same userId is already present, DynamoDB throws ConditionalCheckFailedException and leaves the existing record untouched.
Be Explicit with Composite Keys
For a table with a partition key and a sort key, uniqueness is defined by the pair. It helps to write the condition in a way that makes that intent obvious to the next person reading the code.
This makes the business rule visible in the request itself: only create the order if that exact key pair is new.
Handle Duplicate Attempts Cleanly
A failed conditional write is often a normal duplicate request, not a service outage. Treat it as a controlled application case instead of a generic infrastructure failure.
This is especially useful for APIs that need to return 409 Conflict, idempotent behavior, or a domain-specific message such as "user already exists."
Why Not Read First and Then Write
A common mistake is to call GetItem, decide the item is missing, and then send PutItem. That looks fine in single-user testing, but it is not safe under concurrency. Two requests can both read "missing" and both attempt the insert.
The conditional write closes that race because the check and the write happen together inside DynamoDB.
The result is simpler application code and stronger data integrity.
When to Consider Transactions
If the create operation must also update another item or another table, a single conditional PutItem may not be enough. In that case, move to TransactWriteItems and keep the same design principle: express correctness rules in DynamoDB conditions rather than relying on application-side sequencing.
Common Pitfalls
- Doing a read-then-write flow and assuming it is safe under concurrency.
- Referring to the wrong key attribute names inside
ConditionExpression. - Treating
ConditionalCheckFailedExceptionlike an unexpected crash instead of an expected duplicate case. - Forgetting that overwrites happen on
PutItemby default when the primary key already exists.
One more practical pitfall is swallowing the duplicate exception and retrying blindly. If the request is genuinely a duplicate, retries do not help and only add noise to logs and metrics.
Summary
- '
PutItemoverwrites existing items unless you add a condition.' - Use
attribute_not_existsto make a write succeed only for a new item. - Conditional writes are atomic, so they are safer than a separate read followed by a write.
- Catch duplicate-write failures explicitly and return a meaningful result.
- For composite keys, be clear about the full uniqueness rule in your condition.

