Beginner7 min read

DynamoDB Item-Based Actions

DynamoDB's API splits into three families: item-based actions that work on a single item by its primary key, Query which reads a range within one partition, and Scan which reads everything. This guide is the first family — the four operations you use most: GetItem, PutItem, UpdateItem, DeleteItem. They're the cheapest, fastest calls DynamoDB offers, and getting their distinctions right (especially Put vs Update) prevents a class of accidental-data-loss bugs.

What are DynamoDB's item-based operations?

DynamoDB's item-based operations are the four calls that act on a single item by its full primary key: GetItem reads it, PutItem creates or completely replaces it, UpdateItem modifies specific attributes in place, and DeleteItem removes it. Each addresses exactly one item, making them the fastest, cheapest calls — unlike Query and Scan, which read many.

  • GetItem — read one item by its full primary key.
  • PutItem — create or completely replace one item.
  • UpdateItem — create or modify specific attributes of one item in place.
  • DeleteItem — remove one item by its full primary key.
  • All four require the complete primary key (partition key, plus sort key if the table has one) — they address exactly one item.
  • PutItem overwrites the whole item; UpdateItem is surgical — confusing them is how attributes silently disappear.

The defining trait: one item, full key

Every item-based action targets a single item by its complete primary key. That's what makes them fast and cheap — DynamoDB hashes the partition key, goes straight to the item, done. No filtering, no scanning. If you don't know the full key, these aren't the right tool; that's what Query and Scan are for.

Say you run user accounts keyed by USER#<id>:

PK: USER#204   email, displayName, plan, createdAt
  • GetItem on USER#204 → that user, directly.
  • DeleteItem on USER#204 → removes that user.

Both need the exact key. No key, no item-based action.

PutItem vs UpdateItem — the one that bites

This is the distinction worth internalizing:

  • PutItem writes the entire item. If USER#204 already exists and you PutItem with just {email, displayName}, the existing plan and createdAt attributes are gone — a put replaces the whole item, it doesn't merge.
  • UpdateItem changes only what you name. UpdateItem with a SET email = … leaves every other attribute untouched, and creates the item if it didn't exist (an upsert).
Replace whole itemChange some attributes, keepthe restModify one existing item?PutItemUpdateItem

Rule of thumb: reach for UpdateItem to change an existing item, and use PutItem only when you genuinely mean "write this item as the complete new state." Both PutItem and UpdateItem accept a condition expression so you can make the write conditional ("only if it doesn't already exist").

Item-based actions in DynoTable

Want the raw API calls behind these actions? Assemble the expressions and typed value maps in the DynamoDB expression builder, and convert a plain-JSON item into the API's typed format with the DynamoDB JSON converter.

In DynoTable, that same work is visual: open an item in the grid to read it (a GetItem), edit attributes and commit (an UpdateItem), add or replace a row (a PutItem), or delete one — one item at a time.

Reading a single item in DynoTable's Quick View, with Edit Item and Copy as JSON actions.
Reading a single item in DynoTable's Quick View, with Edit Item and Copy as JSON actions.

Pitfalls + next steps

  • PutItem replaces the whole item — to change a few fields without losing the rest, use UpdateItem.
  • You must know the full primary key — no key means Query/Scan, not an item action.
  • Many items at once? Don't loop these one by one — batch operations fold them into fewer round trips.
  • Need the old/new value back? Set ReturnValues instead of a follow-up GetItem.
  • Related: query vs scan covers the read-many side.

Want to read, write, and delete items without writing a line of API code? Download DynoTable and work with your tables directly.

Cost: one item, one hop

Item-based reads are the cheapest addressable access in DynamoDB. A GetItem on a 2 KB row consumes 1 eventually-consistent RCU (one 4 KB block, rounded up). A Query that returns the same row because you knew the partition key and sort key costs the same capacity — but if you only know the partition key and filter in application code, you pay for every item in the partition.

OperationKeys requiredTypical useCapacity shape
GetItemFull primary keyPoint read by id1 block per item
PutItemFull primary keyCreate or replace whole item1 WCU per KB, rounded
UpdateItemFull primary keyPatch attributesBills for item size written
DeleteItemFull primary keyRemove rowSame as a write on item size
Query + filterPartition (+ optional sort condition)Many items in one partitionSum of matched items

Paste a representative item into the item-size calculator, then multiply by requests per second in the pricing calculator when a hot path uses GetItem in a loop versus one well-keyed Query.

Condition expressions on writes

Both PutItem and UpdateItem accept optional condition expressions. Typical patterns:

  • attribute_not_exists(pk) on put — create-only insert without a race.
  • attribute_exists(pk) on update — refuse to create a stub accidentally.
  • plan = :old on update — optimistic concurrency; retry if another writer changed the plan first.

DeleteItem supports conditions too — delete only if status = :closed, for example. Conditions do not add a separate read charge; DynamoDB evaluates them against the stored item during the write attempt.

Build conditions visually in the DynamoDB expression builder; copy the ConditionExpression plus ExpressionAttributeNames and ExpressionAttributeValues into your SDK call.

Idempotency and overwrite safety

PutItem without a condition is last-writer-wins on the entire item. For webhook handlers or SQS consumers, pair puts with attribute_not_exists on a processed marker attribute, or use UpdateItem with SET processed = :true guarded by attribute_not_exists(processed).

When you need the previous attribute values for an audit log, add ReturnValues on the same UpdateItem instead of a preceding GetItem — one round trip, no read/write race.

Choosing the right item action

IntentCallGuard
Read profile by user idGetItem
Create user if absentPutItemattribute_not_exists(pk)
Change email, keep other fieldsUpdateItemoptional email <> :old
Replace entire config blobPutItemonly when the payload is complete
Remove closed ticketDeleteItemstatus = :closed
Read 50 tickets by known keysBatchGetItemnot 50× GetItem in serial

Staging writes in DynoTable

DynoTable stages UpdateItem and PutItem locally before commit. You review attribute diffs, run optional PartiQL checks, then commit — which maps to the real API calls above. Bulk row deletes batch into BatchWriteItem under the hood with retry on unprocessed items.

For SDK code generation, assemble update clauses in the expression builder and paste the emitted SDK v3 snippet next to your handler tests.

Updated