# Conditional write

> Source: Courseiva IT Certification Glossary — https://courseiva.com/glossary/conditional-write

## Quick definition

A conditional write is like saying, "Only update this file if it hasn't been changed since I last looked at it." It ensures that multiple users or processes don't accidentally overwrite each other's work. This is crucial in databases and cloud storage to keep data accurate. Think of it as a safety rule for updating information.

## Simple meaning

Imagine you and a friend are keeping a shared to-do list on a whiteboard. You both decide to update it at the same time. Without a rule, you might erase what your friend just wrote and replace it with your own, causing confusion. A conditional write works like a rule that says, "Only erase and rewrite this line if nobody else has changed it since you last checked." 

 In technology, especially with cloud storage like Amazon DynamoDB, a conditional write checks a condition before making a change. For example, you might say, "Update the price of this item in the database only if the current price is still $10." If someone else already changed the price to $12, your update will fail, and you'll be notified. This prevents accidental overwrites. 

 This concept is critical because in many computer systems, multiple people or programs might try to update the same piece of information at nearly the same time. Without conditional writes, you could lose data or end up with incorrect information. It helps keep everything consistent and reliable, just like that whiteboard rule keeps your shared to-do list accurate.

## Technical definition

A conditional write is an atomic operation in a database or storage system that performs a write (insert, update, or delete) only if a specified condition evaluates to true. This condition is typically expressed as a Boolean expression that checks the current state of an item, such as attribute values or existence. The operation is part of the broader class of optimistic concurrency control mechanisms, which assume conflicts are rare and validate at write time. 

 In Amazon DynamoDB, a fully managed NoSQL database service on AWS, conditional writes are implemented using the ConditionExpression parameter in APIs like PutItem, UpdateItem, and DeleteItem. The condition can compare attributes using operators like =, <>, <, >, BETWEEN, IN, and function calls like attribute_exists, attribute_not_exists, attribute_type, and begins_with. For example, a PutItem call might include ConditionExpression: "attribute_not_exists(id)" to ensure no item with that primary key already exists, preventing accidental overwrites. 

 The technical mechanism relies on the underlying storage engine's ability to perform a read-then-write operation atomically. DynamoDB achieves this by reading the current item from the storage node, evaluating the condition against that data, and then writing only if the condition holds. If the condition fails, the operation is rejected and no write occurs, returning an error such as ConditionalCheckFailedException. This atomicity ensures that no partial updates or conflicting changes are made. 

 Conditional writes are essential for building distributed applications where multiple clients or processes may access the same data concurrently. They eliminate the need for explicit locking mechanisms in many scenarios, reducing complexity and improving performance. However, they do consume one write capacity unit even if the condition fails, because a read operation is still performed. This is an important cost consideration for production systems. 

 In real-world IT implementations, conditional writes are used in leader election tasks, inventory systems, distributed counters, and any application requiring strong consistency without performance overhead of pessimistic locking. They are a key feature of DynamoDB and are also present in other databases like AWS S3 with its new 'conditional put' feature, and in MongoDB with findAndModify and updates that use query conditions.

## Real-life example

Think of a coffee shop that has a single copy of the day's special menu on the counter. Two baristas, Alice and Bob, both want to update the menu because they ran out of a certain pastry. Alice walks over, reads the menu, sees "Blueberry Muffin - $3.50", and decides to change it to "Sold Out". But at almost the same time, Bob reads the menu, sees the same item, and decides to update the price to $3.75 because of a new shipment. 

 Without a conditional write, the last person to write wins. If Bob writes last, his price change overwrites Alice's sold-out note. Now the menu says "Blueberry Muffin - $3.75" even though it's actually sold out, causing customer confusion. 

 A conditional write in this scenario would be like a rule that says: "Only update the menu if the item's current state matches what you saw when you read it." So Alice's read says the item is available. When she tries to write "Sold Out", the condition checks that the current value is still "Blueberry Muffin - $3.50". If Bob already changed it to "$3.75", her condition fails and her write is rejected. She gets an error and can re-read the fresh data to decide what to do. This ensures the menu always reflects the most current, conflict-free information. 

 This example maps directly to how DynamoDB conditional writes work: you read an item, you specify a condition based on what you saw, and the system only writes if that condition still holds true at the moment of write.

## Why it matters

In practical IT, especially in cloud-based applications, multiple users, services, or automated processes often try to update the same data simultaneously. Without a mechanism like conditional writes, you risk data corruption, lost updates, and inconsistent states. Imagine an e-commerce site where two customers try to buy the last item in stock. Without a conditional write that checks inventory before updating, both could get a success message, but the inventory would be incorrect, leading to overselling and angry customers. 

 Conditional writes matter because they provide a simple, powerful way to implement concurrency control without the overhead of complex locking systems. In distributed databases like DynamoDB, where multiple nodes store replicas of data, keeping things consistent is a major challenge. Conditional writes help you build reliable, scalable applications that handle concurrent updates gracefully. 

 For developers using AWS, understanding conditional writes is fundamental for designing robust serverless applications. They are used in many patterns, such as ensuring a user can only update their own profile, guaranteeing that a task is only claimed by one worker (leader election), or implementing idempotent operations. They are also crucial for maintaining referential integrity in NoSQL databases, where traditional foreign key constraints don't exist. 

 Finally, conditional writes have direct cost implications. In DynamoDB, a failed conditional write still consumes read and write capacity, so poorly designed conditions can increase costs. Knowing when and how to use them efficiently is a skill that separates junior from senior developers.

## Why it matters in exams

Conditional writes are a key topic in the AWS Certified Developer – Associate exam (DVA-C02). This exam places high importance on DynamoDB's read and write operations, including conditional writes. According to the official exam guide, the domain 'Development with AWS Services' includes DynamoDB operations, and conditional writes are explicitly mentioned in the context of 'implementing data consistency and concurrency control'. 

 Exam questions often present scenario-based problems where you need to choose the correct operation to prevent data loss or ensure consistency. For example, you might be asked: 'A developer needs to update a DynamoDB item only if the item's version attribute matches a certain value. Which parameter should they use?' The answer is ConditionExpression with the attribute_exists or attribute_not_exists function. 

 Another common question type involves understanding the cost implications. You might see: 'How many write capacity units (WCUs) does a failed conditional write consume?' The answer is one WCU, because DynamoDB performs a read to evaluate the condition. A failed conditional write also consumes one RCU (read capacity unit) if the item is at least 4KB, but the exam typically focuses on write consumption. 

 The exam also tests your ability to choose between conditional writes and other concurrency mechanisms like optimistic locking with version numbers or pessimistic locking using transactions. You need to know that conditional writes are simpler and cheaper for low-contention scenarios, while DynamoDB Transactions (which are more expensive) should be used when multiple items must be updated atomically. 

the exam may ask about the behavior of conditional writes in the context of global secondary indexes (GSIs) or local secondary indexes (LSIs). The condition is evaluated on the base table attributes, not on index attributes. Understanding this distinction is critical for avoiding tricky exam traps.

## How it appears in exam questions

In the AWS Developer-Associate exam, questions about conditional writes frequently appear in three main patterns: scenario-based, configuration-based, and troubleshooting-based. 

 Scenario-based questions: These present a real-world problem where multiple clients update the same data. For example: 'A social media app allows users to update their profile bio. Two users simultaneously send update requests. How can the developer ensure that Bob's update does not overwrite Alice's changes?' The correct answer will involve using a conditional write with a version attribute that is checked before updating. The question might ask which DynamoDB API operation to use (UpdateItem with ConditionExpression) or which parameter to set. 

 Configuration-based questions: These ask about the specific syntax of ConditionExpression. For instance: 'Which expression ensures a PutItem operation only succeeds if the item does not already exist?' The answer is 'attribute_not_exists(PK)'. Or 'Which condition ensures that an item's price attribute is updated only if its current value is less than 100?' Answer: 'price < :threshold'. These questions test your familiarity with DynamoDB condition expression language. 

 Troubleshooting-based questions: These present an issue where a conditional write is failing unexpectedly. For example: 'A developer is using ConditionExpression attribute_exists(PK) but the conditional write always fails even though the item exists. What is the most likely cause?' The answer might be that the condition expression uses the wrong attribute name, or that the write is being performed on a different partition key than intended. Another common troubleshooting question involves verifying that the condition expression is syntactically correct-forgetting colons for value placeholders is a typical mistake. 

 Another pattern involves comparing conditional writes with DynamoDB Transactions. You might be asked: 'When would a developer choose a conditional write over a DynamoDB Transaction?' The answer is when only a single item needs to be updated conditionally, because transactions are more expensive and have higher latency. 

 Finally, the exam might include questions about error handling. For example: 'What exception is thrown when a conditional write fails in DynamoDB?' The answer is ConditionalCheckFailedException. Understanding the exception name helps in identifying the error in code responses.

## Example scenario

You are building a simple online voting app where users can vote for their favorite dish in a company contest. Each dish has a vote count stored in a DynamoDB table. The table has a primary key 'dish_id' and a numeric attribute 'votes'. 

 You want to ensure that two users voting at the same time don't cause the vote count to be incorrect. Without a conditional write, two simultaneous votes might both read the same initial vote count (say 10), each increment it to 11 locally, and then both write 11 back. The result would be 11 instead of the correct 12. 

 To fix this, you decide to use an optimistic locking pattern with a 'version' attribute. Each dish item has a 'version' number that starts at 1. When a user votes, your code reads the item, gets the current vote count (10) and current version (1). Then it performs an UpdateItem operation with ConditionExpression: 'version = :old_version' and an UpdateExpression that sets 'votes = votes + :inc' and 'version = version + :new_version'. You set ':old_version' to 1 and ':inc' to 1. 

 If another user's vote was processed before yours and incremented the version to 2, your conditional write will fail because the version is no longer 1. You catch the ConditionalCheckFailedException and retry by reading the updated item again. This ensures every vote is counted exactly once. 

 This scenario is a classic example of using conditional writes for atomic counters in a distributed system. It demonstrates how you can build robust, consistent applications even with concurrent access.

## Common mistakes

- **Mistake:** Using a condition on a non-existent attribute without checking if it exists first.
  - Why it is wrong: If the attribute does not exist, the condition might evaluate to a false (if comparing) or cause an error. For example, using 'price < 100' on an item without a 'price' attribute will cause the condition to fail or behave unexpectedly.
  - Fix: First check if the attribute exists using attribute_exists(attributeName) or handle the missing attribute with attribute_not_exists. Alternatively, use a default value in the condition.
- **Mistake:** Assuming a failed conditional write does not consume any capacity.
  - Why it is wrong: A failed conditional write still consumes one Write Capacity Unit (WCU) and one Read Capacity Unit (RCU) for items up to 4KB. This can lead to unexpected costs under high contention.
  - Fix: Plan for the capacity consumption of conditional writes even when they fail. In high-contention scenarios, consider using a different approach like DynamoDB transactions or application-level retries with exponential backoff.
- **Mistake:** Using the ConditionExpression on a Global Secondary Index (GSI) attribute.
  - Why it is wrong: ConditionExpression only works on attributes of the base table, not on attributes of a GSI. If you try to condition on a GSI key attribute, the condition will not be evaluated correctly.
  - Fix: Always use condition expressions on base table attributes. If you need to condition on a GSI attribute, reconsider your data model or use a different design pattern.
- **Mistake:** Forgetting to use the colon prefix for expression attribute values in ConditionExpression.
  - Why it is wrong: In DynamoDB, all expression attribute values must start with a colon (:), like ':value1'. Omitting this causes a validation error.
  - Fix: Always prefix your value placeholders with a colon. For example: ConditionExpression: 'price = :expected_price'.

## Exam trap

{"trap":"Choosing DynamoDB Transactions over a simple conditional write for a single-item update that only requires a condition check.","why_learners_choose_it":"Learners may think that transactions are always better for consistency, or they may remember that transactions can handle complex conditions. They may not realize that transactions are overkill and more expensive for single-item operations.","how_to_avoid_it":"Remember that DynamoDB Transactions (using TransactWriteItems) are designed for multiple-item atomic operations. For a single-item conditional write, use the simpler and cheaper PutItem, UpdateItem, or DeleteItem with ConditionExpression. Transactions cost 2x more write capacity (two WCUs per item). The exam expects you to choose the most efficient solution."}

## Commonly confused with

- **Conditional write vs Optimistic locking:** Optimistic locking is a broader strategy that often uses a version number attribute, while a conditional write is the specific mechanism that enforces the version check. Optimistic locking requires conditional writes to implement, but the term 'conditional write' refers only to the atomic check-and-write operation itself. (Example: Optimistic locking is the plan; a conditional write is the execution of that plan when you check the version before writing.)
- **Conditional write vs Pessimistic locking:** Pessimistic locking involves locking a data item to prevent others from accessing it, often with a database lock or a distributed lock. Conditional writes do not lock data; they just check a condition at write time. Pessimistic locking is more conservative and can lead to lower concurrency, while conditional writes (optimistic) allow higher concurrency but require retries on conflict. (Example: Pessimistic locking is like reserving a book so no one else can read it. A conditional write is like only buying the book if the price tag still shows the same price you saw.)
- **Conditional write vs Atomic counters:** Atomic counters refer to the ability to increment a counter in one atomic step. DynamoDB supports atomic counters with UpdateExpression 'SET votes = votes + :inc'. This operation does not automatically include a condition. Conditional writes add a check before the atomic update, making it a conditional update. Atomic counters alone can still have conflicts if two processes read the same old value; added conditions solve that. (Example: Atomic counter: 'increment the count by 1' without checking. Conditional write: 'increment the count by 1, but only if no one else changed it between my read and write'.)

## Step-by-step breakdown

1. **Read the current item** — Your application performs a GetItem or Query operation to retrieve the current state of the item you want to update. You note the values of attributes that you will use in the condition, such as a version number or a timestamp.
2. **Define the condition expression** — Based on the read, you construct a ConditionExpression that expresses the condition that must be true for the write to proceed. For example, 'version = :current_version' ensures the item hasn't changed since you read it.
3. **Send the conditional write request** — You issue a PutItem, UpdateItem, or DeleteItem API call (in DynamoDB) with the ConditionExpression parameter. The request includes the updated item data and the expression attribute values for the condition.
4. **Evaluation by the database** — DynamoDB reads the item from the storage node atomically. It checks whether your condition holds true against the current item. This read-and-check happens as one atomic operation, so no other write can interfere during this instant.
5. **Condition passes: write occurs** — If the condition evaluates to true, the write operation is performed. The item is updated or deleted as requested. A success response is returned to the application.
6. **Condition fails: write is rejected** — If the condition evaluates to false, the write is rejected. DynamoDB returns a ConditionalCheckFailedException. No changes are made to the item, but capacity units are still consumed for the read and the attempted write.

## Practical mini-lesson

As a developer working with Amazon DynamoDB, conditional writes are one of the most powerful tools you have for building reliable, concurrent applications. They allow you to update data with confidence, knowing that you won't accidentally overwrite someone else's changes. The key to using them effectively is understanding the ConditionExpression syntax and the different functions available. 

 The ConditionExpression can use comparison operators like =, <>, <, >, <=, >=, BETWEEN, and IN. It also supports logical operators AND, OR, and NOT. You can nest functions like attribute_exists, attribute_not_exists, attribute_type, and begins_with. For example, to ensure a new user's email is unique, you might use ConditionExpression: 'attribute_not_exists(email)' on a global secondary index, but remember that DynamoDB only supports condition expressions on base table attributes. In practice, you would design your primary key to include a unique identifier or use a separate table. 

 A common pattern is optimistic locking using a version number. You retrieve the item, increment the version, and set a condition that the current version matches what you read. If the condition fails, you retry by re-reading the item and trying again. This pattern is used in many enterprise applications, such as inventory management where you need to decrement stock count only if stock is available. For example: ConditionExpression: 'stock > :zero' and UpdateExpression: 'SET stock = stock - :one'. This ensures you never oversell. 

 What can go wrong? One frequent issue is that developers forget that a failed conditional write still consumes capacity. If you have a high rate of conflicts, you can burn through your provisioned capacity quickly. To mitigate this, use exponential backoff when retrying, and consider an alternative design like using DynamoDB Streams or application-level queues to serialize updates. 

 Another pitfall is using the condition on an attribute that is part of a secondary index but not the base table. DynamoDB will not evaluate the condition based on the index-it only sees the base table data. If you need to condition on a secondary index attribute, you must include that attribute in the base item as well. 

 Professionals also need to be aware of the cost model: each conditional write consumes one WCU even if it fails. In a system with many concurrent users, you might see a high percentage of failed writes, leading to unexpected bills. Consider using DynamoDB 'conditional writes' with 'ReturnValues' to get the old item if you need it for debugging. 

 In a real deployment, you'll pair conditional writes with proper error handling in your code. Use try-catch blocks to handle ConditionalCheckFailedException and decide whether to retry, log, or alert. This ensures your application remains robust under load.

## Memory tip

Conditional write: 'Write only if the condition is true', just like a bouncer at a club who only lets you in if you're on the list.

## FAQ

**How does a conditional write differ from a regular write in DynamoDB?**

A regular write (PutItem, UpdateItem) will simply overwrite an existing item regardless of its current state. A conditional write only performs the write if the specified condition on the item's attributes is met. If the condition fails, the write is rejected, and no change occurs.

**Do conditional writes consume more capacity than regular writes?**

A conditional write that succeeds consumes the same capacity as a regular write (one WCU for items up to 1KB) plus an additional RCU to read the item for condition evaluation. A failed conditional write still consumes one WCU and one RCU, because the system still reads the item and attempts the write.

**Can I use a conditional write on a global secondary index (GSI) attribute?**

No. Condition expressions in DynamoDB can only refer to attributes of the base table. They cannot reference attributes that are part of a GSI key schema. If you need to condition on such data, you must include the attribute in the base table.

**What happens if my ConditionExpression contains a syntax error?**

DynamoDB will return a ValidationException with a message indicating the specific error, such as 'Invalid ConditionExpression'. The write will not be attempted. Always test your condition expressions with small sample data.

**Can I use conditional writes with DynamoDB Streams?**

Yes. If a conditional write succeeds, the change is recorded in the DynamoDB Stream. If it fails, no stream event is generated because no data was modified. This is important for downstream processing that reacts to data changes.

**Are conditional writes supported in all DynamoDB API operations?**

Conditional writes are supported in PutItem, UpdateItem, and DeleteItem operations. They are not supported in BatchWriteItem (for batch operations) or TransactWriteItems (though transactions have their own condition checking mechanism via CheckItem).

## Summary

A conditional write is a foundational concept in distributed data storage that allows you to update data only when a specific condition is met. It prevents race conditions and data corruption in concurrent environments. The core idea is simple: before writing, the system checks that the data hasn't changed since you last read it, ensuring that your write is based on the current state. 

 In Amazon DynamoDB, conditional writes are implemented via ConditionExpression, which can compare attributes, check existence, or use pattern matching. They are a key tool for building reliable serverless applications on AWS, especially when multiple clients or services access the same data. Understanding how they work, their cost implications, and common pitfalls is critical for the AWS Developer-Associate exam. 

 For exam success, remember that conditional writes are atomic, that a failed write still consumes capacity, and that they only work on base table attributes. Practice writing ConditionExpression syntax and know the difference between conditional writes and DynamoDB Transactions. Use the memory tip: 'Write only if the condition is true' to anchor the concept. With this understanding, you'll be able to answer scenario-based, configuration-based, and troubleshooting questions confidently on exam day.

---

Practice questions and the full interactive page: https://courseiva.com/glossary/conditional-write
