DynamoDB

AWS managed NoSQL key-value database - serverless, millisecond latency, auto-scaling

TL;DR

What: A fully managed NoSQL key-value database by AWS.

Why: Serverless, single-digit millisecond latency, auto-scaling, pay-per-use.

Quick Start

Local development with Docker:

docker run -p 8000:8000 amazon/dynamodb-local

Install AWS CLI:

pip install awscli
aws configure  # Use dummy values for local

Create table:

aws dynamodb create-table \
  --table-name Users \
  --attribute-definitions AttributeName=userId,AttributeType=S \
  --key-schema AttributeName=userId,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --endpoint-url http://localhost:8000

Or use AWS SDK:

import { DynamoDBClient, CreateTableCommand } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient({ region: "us-east-1" });

Cheatsheet

OperationAWS CLI
List tablesaws dynamodb list-tables
Describe tableaws dynamodb describe-table --table-name Name
Put itemaws dynamodb put-item --table-name Name --item '{}'
Get itemaws dynamodb get-item --table-name Name --key '{}'
Queryaws dynamodb query --table-name Name ...
Scanaws dynamodb scan --table-name Name
Delete itemaws dynamodb delete-item --table-name Name --key '{}'

Gotchas

CRUD with SDK (JavaScript)

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand, GetCommand, QueryCommand, DeleteCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

// Put item
await docClient.send(new PutCommand({
  TableName: "Users",
  Item: { userId: "123", name: "John", email: "[email protected]" }
}));

// Get item
const { Item } = await docClient.send(new GetCommand({
  TableName: "Users",
  Key: { userId: "123" }
}));

// Query (requires partition key)
const { Items } = await docClient.send(new QueryCommand({
  TableName: "Orders",
  KeyConditionExpression: "userId = :uid",
  ExpressionAttributeValues: { ":uid": "123" }
}));

// Delete
await docClient.send(new DeleteCommand({
  TableName: "Users",
  Key: { userId: "123" }
}));

Key design

// Simple primary key (partition key only)
{ userId: "HASH" }

// Composite primary key
{ userId: "HASH", orderId: "RANGE" }

// Global Secondary Index (GSI)
// Allows querying by different attributes

Conditional writes

await docClient.send(new PutCommand({
  TableName: "Users",
  Item: { userId: "123", name: "John" },
  ConditionExpression: "attribute_not_exists(userId)"
}));

Next Steps