Database
Amazon DynamoDB
Overview
Amazon DynamoDB is a fully managed NoSQL database service provided by AWS. It can store and retrieve any amount of data and serve any level of request traffic, providing serverless, single-digit millisecond performance at any scale.
Details
DynamoDB was announced by Amazon in 2012, developed based on the Dynamo database used internally at Amazon.com. As a fully managed service, it automates server management, patching, software upgrades, replication, and backups, allowing developers to focus on application development.
Key features of DynamoDB:
- Serverless and fully managed
- Single-digit millisecond response times
- Automatic scaling
- Global tables (multi-region)
- ACID transactions
- Fine-grained access control
- DynamoDB Accelerator (DAX) for in-memory caching
- DynamoDB Streams for monitoring data changes
- Encryption (at rest and in transit)
- Point-in-time recovery
Advantages and Disadvantages
Advantages
- Serverless: No server management required, reducing operational overhead
- High performance: Single-digit millisecond latency
- Auto-scaling: Automatically scales based on traffic
- High availability: 99.999% SLA guarantee
- Security: Comprehensive security with encryption and IAM integration
- AWS integration: Tight integration with other AWS services
- Cost efficiency: Pay-per-use pricing model
Disadvantages
- Vendor lock-in: Dependent on AWS architecture
- SQL limitations: Cannot use SQL queries
- Data model constraints: Design complexity due to NoSQL constraints
- Cost: Can become expensive for large-scale usage
- Learning curve: Need to learn DynamoDB-specific concepts and limitations
Key Links
Code Examples
Setup & Configuration
# AWS CLI installation and configuration
aws configure
# DynamoDB Local (for development)
docker run -p 8000:8000 amazon/dynamodb-local
# AWS SDK installation (Node.js)
npm install aws-sdk
# AWS SDK installation (Python)
pip install boto3
Basic Operations (Table Management)
const AWS = require('aws-sdk')
// DynamoDB client configuration
const dynamodb = new AWS.DynamoDB.DocumentClient({
region: 'us-east-1'
})
// Create table
const createTableParams = {
TableName: 'Users',
KeySchema: [
{ AttributeName: 'userId', KeyType: 'HASH' }, // Partition key
{ AttributeName: 'timestamp', KeyType: 'RANGE' } // Sort key
],
AttributeDefinitions: [
{ AttributeName: 'userId', AttributeType: 'S' },
{ AttributeName: 'timestamp', AttributeType: 'N' }
],
BillingMode: 'PAY_PER_REQUEST' // On-demand
}
// List tables
const tables = await dynamodb.listTables().promise()
console.log(tables.TableNames)
Basic Operations (CRUD)
// Create item (Create)
const putParams = {
TableName: 'Users',
Item: {
userId: 'user123',
timestamp: Date.now(),
name: 'John Doe',
email: '[email protected]',
age: 30,
address: {
city: 'New York',
state: 'NY'
},
tags: ['engineer', 'javascript']
}
}
await dynamodb.put(putParams).promise()
// Read item (Read)
const getParams = {
TableName: 'Users',
Key: {
userId: 'user123',
timestamp: 1640995200000
}
}
const result = await dynamodb.get(getParams).promise()
console.log(result.Item)
// Update item (Update)
const updateParams = {
TableName: 'Users',
Key: {
userId: 'user123',
timestamp: 1640995200000
},
UpdateExpression: 'SET age = :age, email = :email',
ExpressionAttributeValues: {
':age': 31,
':email': '[email protected]'
},
ReturnValues: 'UPDATED_NEW'
}
await dynamodb.update(updateParams).promise()
// Delete item (Delete)
const deleteParams = {
TableName: 'Users',
Key: {
userId: 'user123',
timestamp: 1640995200000
}
}
await dynamodb.delete(deleteParams).promise()
Queries and Scans
// Query (search by partition key)
const queryParams = {
TableName: 'Users',
KeyConditionExpression: 'userId = :userId',
ExpressionAttributeValues: {
':userId': 'user123'
},
ScanIndexForward: false, // Descending order
Limit: 10
}
const queryResult = await dynamodb.query(queryParams).promise()
console.log(queryResult.Items)
// Scan (full table search)
const scanParams = {
TableName: 'Users',
FilterExpression: 'age > :age',
ExpressionAttributeValues: {
':age': 25
}
}
const scanResult = await dynamodb.scan(scanParams).promise()
console.log(scanResult.Items)
// Batch get
const batchGetParams = {
RequestItems: {
'Users': {
Keys: [
{ userId: 'user123', timestamp: 1640995200000 },
{ userId: 'user456', timestamp: 1640995300000 }
]
}
}
}
const batchResult = await dynamodb.batchGet(batchGetParams).promise()
Indexing & Optimization
// Create Global Secondary Index (GSI)
const updateTableParams = {
TableName: 'Users',
GlobalSecondaryIndexUpdates: [
{
Create: {
IndexName: 'EmailIndex',
KeySchema: [
{ AttributeName: 'email', KeyType: 'HASH' }
],
Projection: { ProjectionType: 'ALL' },
BillingMode: 'PAY_PER_REQUEST'
}
}
],
AttributeDefinitions: [
{ AttributeName: 'email', AttributeType: 'S' }
]
}
// Query using GSI
const gsiQueryParams = {
TableName: 'Users',
IndexName: 'EmailIndex',
KeyConditionExpression: 'email = :email',
ExpressionAttributeValues: {
':email': '[email protected]'
}
}
const gsiResult = await dynamodb.query(gsiQueryParams).promise()
Practical Examples
// Transactions
const transactParams = {
TransactItems: [
{
Put: {
TableName: 'Orders',
Item: {
orderId: 'order123',
userId: 'user123',
amount: 1000,
status: 'created'
}
}
},
{
Update: {
TableName: 'Users',
Key: { userId: 'user123' },
UpdateExpression: 'ADD totalOrders :inc',
ExpressionAttributeValues: { ':inc': 1 }
}
}
]
}
await dynamodb.transactWrite(transactParams).promise()
// Conditional write
const conditionalPutParams = {
TableName: 'Users',
Item: {
userId: 'user789',
name: 'Jane Smith',
email: '[email protected]'
},
ConditionExpression: 'attribute_not_exists(userId)'
}
// Enable DynamoDB Streams
const enableStreamsParams = {
TableName: 'Users',
StreamSpecification: {
StreamEnabled: true,
StreamViewType: 'NEW_AND_OLD_IMAGES'
}
}
Best Practices
// Batch write
const batchWriteParams = {
RequestItems: {
'Users': [
{
PutRequest: {
Item: { userId: 'user001', name: 'User 1' }
}
},
{
DeleteRequest: {
Key: { userId: 'user002' }
}
}
]
}
}
await dynamodb.batchWrite(batchWriteParams).promise()
// Pagination
async function scanAllItems(tableName) {
let items = []
let lastEvaluatedKey = null
do {
const params = {
TableName: tableName,
...(lastEvaluatedKey && { ExclusiveStartKey: lastEvaluatedKey })
}
const result = await dynamodb.scan(params).promise()
items = items.concat(result.Items)
lastEvaluatedKey = result.LastEvaluatedKey
} while (lastEvaluatedKey)
return items
}
// Error handling
try {
await dynamodb.put(putParams).promise()
} catch (error) {
if (error.code === 'ConditionalCheckFailedException') {
console.log('Conditional check failed')
} else if (error.code === 'ProvisionedThroughputExceededException') {
console.log('Throughput limit exceeded')
}
}
AWS CLI Operations
# 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
# Put item
aws dynamodb put-item \
--table-name Users \
--item '{"userId": {"S": "user123"}, "name": {"S": "John Doe"}}'
# Get item
aws dynamodb get-item \
--table-name Users \
--key '{"userId": {"S": "user123"}}'
# List tables
aws dynamodb list-tables