DynamoDB: CRUD Operations & Queries
AWS SDK v3 — Node.js
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { DynamoDBDocumentClient, GetCommand, PutCommand, UpdateCommand,
DeleteCommand, QueryCommand, ScanCommand, TransactWriteCommand } from '@aws-sdk/lib-dynamodb'
const client = new DynamoDBClient({ region: 'eu-west-1' })
const db = DynamoDBDocumentClient.from(client)
const TABLE = 'MyApp'GetItem & PutItem
// GetItem — fetch by exact primary key
const { Item } = await db.send(new GetCommand({
TableName: TABLE,
Key: { PK: 'USER#alice', SK: 'PROFILE' },
ConsistentRead: true, // strong consistency
}))
// PutItem — create or overwrite
await db.send(new PutCommand({
TableName: TABLE,
Item: {
PK: 'USER#alice',
SK: 'PROFILE',
name: 'Alice',
email: 'alice@example.com',
createdAt: new Date().toISOString(),
},
// Prevent overwrite if item already exists
ConditionExpression: 'attribute_not_exists(PK)',
}))
// UpdateItem — modify specific attributes without overwriting whole item
await db.send(new UpdateCommand({
TableName: TABLE,
Key: { PK: 'USER#alice', SK: 'PROFILE' },
UpdateExpression: 'SET #name = :name, updatedAt = :ts ADD loginCount :one',
ExpressionAttributeNames: { '#name': 'name' }, // 'name' is a reserved word
ExpressionAttributeValues: {
':name': 'Alice Smith',
':ts': new Date().toISOString(),
':one': 1,
},
}))Query & Scan
// Query — efficient, uses key conditions (PK required)
const { Items } = await db.send(new QueryCommand({
TableName: TABLE,
KeyConditionExpression: 'PK = :pk AND begins_with(SK, :prefix)',
FilterExpression: '#status = :active', // applied after key filter — still reads all matching keys
ExpressionAttributeNames: { '#status': 'status' },
ExpressionAttributeValues: {
':pk': 'USER#alice',
':prefix': 'ORDER#',
':active': 'active',
},
ScanIndexForward: false, // DESC order by sort key
Limit: 10, // max items per page
}))
// Paginate — LastEvaluatedKey signals more pages exist
async function queryAll(pk: string) {
const items = []
let lastKey
do {
const { Items: page, LastEvaluatedKey } = await db.send(new QueryCommand({
TableName: TABLE,
KeyConditionExpression: 'PK = :pk',
ExpressionAttributeValues: { ':pk': pk },
ExclusiveStartKey: lastKey,
}))
items.push(...(page ?? []))
lastKey = LastEvaluatedKey
} while (lastKey)
return items
}
// Scan — reads entire table (avoid in production unless necessary)
const { Items: all } = await db.send(new ScanCommand({
TableName: TABLE,
FilterExpression: 'contains(tags, :tag)',
ExpressionAttributeValues: { ':tag': 'featured' },
}))Transactions
// TransactWrite — all-or-nothing across up to 100 items in one table (or multiple)
await db.send(new TransactWriteCommand({
TransactItems: [
{
Update: {
TableName: TABLE,
Key: { PK: 'PRODUCT#widget', SK: 'METADATA' },
UpdateExpression: 'ADD stock :minus',
ConditionExpression: 'stock >= :qty',
ExpressionAttributeValues: { ':minus': -1, ':qty': 1 },
}
},
{
Put: {
TableName: TABLE,
Item: {
PK: 'USER#alice',
SK: 'ORDER#2026-999',
productId: 'widget',
qty: 1,
status: 'pending',
},
ConditionExpression: 'attribute_not_exists(PK)',
}
}
]
}))Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free