Use Conditional Writes to Enforce Business Logic in DynamoDB

Learn conditional writes to avoid race conditions, enforce uniqueness, and lock down writes.

One of the most underrated features in DynamoDB is conditional writes.

Most users treat DynamoDB as a simple key-value datastore: put an item in, get an item out.

But DynamoDB has a wealth of powerful features to support most modern workloads.

One of these is to enforce business logic directly at the database level (in an atomic operation) without needing extra read operations or middleware logic.

This does a lot for performance and consistency in your database.

Let’s break this down.

What are conditional writes?

In DynamoDB, you can use a ConditionExpression within the following write operations:

  • PutItem

  • UpdateItem

  • DeleteItem

This tells DynamoDB to only perform the write if the given condition is met. Otherwise the write is rejected.

This acts as a logic gate for writes.

Imagine the following example: you want to create a user with a unique username. 

Usually to do this, you would need to have a read to check if the username exists and then do a write if it doesn’t (and return an error if it does).

But with conditional writes, you can skip the read entirely.

Here’s the code in a DynamoDB PutItem:

await dynamodbClient.send(new PutItemCommand({
  TableName: "users",
  Item: marshall({
     username: "jason123",
     email: "[email protected]",
  }),
  ConditionExpression: 'attribute_not_exists(username)'
}))

This write of a new user will only succeed if the username value does not exist in the table, effeciently enforcing uniqueness with one atomic operation.

Some use cases for conditional writes

Some useful use cases for conditional writes can be:

  • preventing duplicate orders 

  • making sure a user doesn’t apply a coupon twice

  • enforce account limits (e.g. max 5 devices per user)

  • avoiding overwrites in race conditions

These are all business logic constraints that commonly appear in applications.

Conditional writes allow you to support these constraints with minimal latency and complexity.

Handling conditional failures

If a condition fails, DynamoDB will throw a ConditionalCheckFailedException. 

You can catch this error and return a more readable message to the user like: 

“This coupon has already been used”

Remember, a conditional fail is expected behaviour, not a bug. So display it as the normal flow when an item already exists.

Summary

Conditional Expressions in DynamoDB are powerful and keep conditional writes more efficient.

They let you enforce rules like uniqeness, resource limits, idempotency and concurrency control all at the database write layer with full atomicity.

Whenever you need conditional writes in your application, verify if the condition can instead be done on your DynamoDB query before.

👋 My name is Uriel Bitton and I hope you learned something in this edition of Excelling With DynamoDB.

📅 If you're looking for help with DynamoDB, let's have a quick chat.

🙌 I hope to see you in next week's edition!