Skip to content
Quest 07Intermediate14 min

Boost Mew's Stats

Battle statistics change fast! If two players battle at the same time, you could have a race condition. If both read "Wins: 10", add 1, and write "Wins: 11", one win is lost forever. DynamoDB solves this with Atomic Counters using the ADD action.
Start the lesson

What you'll learn

  • Race conditions occur when parallel updates overwrite each other.
  • The ADD action atomically increments numeric values in DynamoDB.
  • Atomic increments are not idempotent: retrying an uncertain write can count twice. Use deduplication or a transaction when exact counts matter.

Section 01

The Race Condition Problem

Imagine thousands of players battling at once. A traditional read-modify-write pattern is dangerous:

  • Read current stats (Wins: 10)
  • Application adds 1 (Wins: 11)
  • Write back (Wins: 11)
AshAWS SDK v3GaryAWS SDK v3DynamoDBtableP0P1P2P3CONSUMED0

Ready · 16 steps · Orbi

This animation plays when you scroll to it. Press Play to start it now.

All steps as text
  1. Trainer Ash sends GetItem to the Pokemon table with Name = "Mew". Read the counter first.
  2. DynamoDB hashes "Mew" to 416a585c, which routes the request to partition P0.
  3. P0 returns Mew (BattlesWon 0).
  4. Trainer Gary sends GetItem to the Pokemon table with Name = "Mew". Reads before A has written.
  5. DynamoDB hashes "Mew" to 416a585c, which routes the request to partition P0.
  6. P0 returns Mew (BattlesWon 0).
  7. Trainer Ash sends UpdateItem to the Pokemon table with Name = "Mew". Writes back 0 + 1: SET BattlesWon = :wins
  8. DynamoDB hashes "Mew" to 416a585c, which routes the request to partition P0.
  9. P0 updates Mew (BattlesWon = 1).
  10. This call consumed 1 WCU.
  11. DynamoDB responds with success: Ash's write succeeded.
  12. Trainer Gary sends UpdateItem to the Pokemon table with Name = "Mew". Also writes back 0 + 1: SET BattlesWon = :wins
  13. DynamoDB hashes "Mew" to 416a585c, which routes the request to partition P0.
  14. Trainer Gary's write to Mew lands on P0 and silently replaces the other change.
  15. This call consumed 1 WCU.
  16. DynamoDB responds with success: two wins recorded, but BattlesWon shows 1.

Section 02

Atomic Counters to the Rescue

DynamoDB supports atomic updates. You tell it "Add 1 to this attribute" rather than "Set this attribute to 11". Each update is atomic, so concurrent increments do not overwrite one another. A timeout can still leave the outcome uncertain; blindly retrying can increment again.

Atomic Increment ExampleJavaScript
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: "Pokemon",
  Key: { Name: "Mew" },
  UpdateExpression: "ADD BattlesWon :inc",
  ExpressionAttributeValues: {
    ":inc": 1
  }
}));

Practice

Your turn

Mew won another battle. Use UpdateCommand with the ADD action to increase BattlesWon by 1. It's atomic, so it beats reading the value and writing it back.
Use ADD in UpdateExpression to increment BattlesWon by 1.
Tab inserts two spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the code.
Simulated — no AWS calls

Check

Check your understanding

Quick Quiz · one question, as many tries as you need.

Why should you use atomic counters instead of read-modify-write for game stats?

Choose one answer.