Appearance
Generate UUID in DynamoDB
DynamoDB doesn't have built-in UUID generation functions. UUIDs are generated in your application code and stored as String attributes. Here's how to implement UUID generation for DynamoDB:
javascript
// Node.js with AWS SDK v3
import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
import { v4 as uuidv4, v1 as uuidv1 } from 'uuid';
const client = new DynamoDBClient({ region: 'us-east-1' });
// Generate UUID and store in DynamoDB
const userId = uuidv4();
const command = new PutItemCommand({
TableName: 'Users',
Item: {
id: { S: userId },
name: { S: 'John Doe' },
email: { S: '[email protected]' },
createdAt: { S: new Date().toISOString() }
}
});
await client.send(command);
Since DynamoDB requires application-level UUID generation, here are patterns for different use cases:
javascript
// UUID as partition key (even distribution)
const userTable = {
TableName: 'Users',
KeySchema: [
{ AttributeName: 'id', KeyType: 'HASH' } // Partition key
],
AttributeDefinitions: [
{ AttributeName: 'id', AttributeType: 'S' }
]
};
// UUID with time-based sort key
const eventsTable = {
TableName: 'Events',
KeySchema: [
{ AttributeName: 'userId', KeyType: 'HASH' }, // Partition key
{ AttributeName: 'eventId', KeyType: 'RANGE' } // Sort key (TimeUUID)
],
AttributeDefinitions: [
{ AttributeName: 'userId', AttributeType: 'S' },
{ AttributeName: 'eventId', AttributeType: 'S' }
]
};
AWS SDK Integration
Node.js with DynamoDB Document Client:
javascript
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand, GetCommand, QueryCommand } from '@aws-sdk/lib-dynamodb';
import { v4 as uuidv4, v1 as uuidv1 } from 'uuid';
const client = new DynamoDBClient({ region: 'us-east-1' });
const docClient = DynamoDBDocumentClient.from(client);
class UserService {
async createUser(name, email) {
const userId = uuidv4();
const item = {
id: userId,
name,
email,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
await docClient.send(new PutCommand({
TableName: 'Users',
Item: item
}));
return userId;
}
async getUser(userId) {
const result = await docClient.send(new GetCommand({
TableName: 'Users',
Key: { id: userId }
}));
return result.Item;
}
async createEvent(userId, eventType, data) {
const eventId = uuidv1(); // Time-based for chronological ordering
const item = {
userId,
eventId,
eventType,
data,
timestamp: new Date().toISOString()
};
await docClient.send(new PutCommand({
TableName: 'Events',
Item: item
}));
return eventId;
}
async getUserEvents(userId, limit = 10) {
const result = await docClient.send(new QueryCommand({
TableName: 'Events',
KeyConditionExpression: 'userId = :userId',
ExpressionAttributeValues: {
':userId': userId
},
ScanIndexForward: false, // Latest first
Limit: limit
}));
return result.Items;
}
}
Python with Boto3:
python
import boto3
import uuid
from datetime import datetime
from decimal import Decimal
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
class UserService:
def __init__(self):
self.users_table = dynamodb.Table('Users')
self.events_table = dynamodb.Table('Events')
def create_user(self, name, email):
user_id = str(uuid.uuid4())
item = {
'id': user_id,
'name': name,
'email': email,
'createdAt': datetime.now().isoformat(),
'updatedAt': datetime.now().isoformat()
}
self.users_table.put_item(Item=item)
return user_id
def get_user(self, user_id):
response = self.users_table.get_item(Key={'id': user_id})
return response.get('Item')
def create_event(self, user_id, event_type, data):
event_id = str(uuid.uuid1()) # Time-based UUID
item = {
'userId': user_id,
'eventId': event_id,
'eventType': event_type,
'data': data,
'timestamp': datetime.now().isoformat()
}
self.events_table.put_item(Item=item)
return event_id
def get_user_events(self, user_id, limit=10):
response = self.events_table.query(
KeyConditionExpression='userId = :userId',
ExpressionAttributeValues={':userId': user_id},
ScanIndexForward=False, # Latest first
Limit=limit
)
return response['Items']
# Usage
service = UserService()
user_id = service.create_user('Jane Doe', '[email protected]')
event_id = service.create_event(user_id, 'login', {'ip': '192.168.1.1'})
Java with AWS SDK:
java
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;
import java.util.UUID;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
public class UserService {
private final DynamoDbClient dynamoDb;
public UserService() {
this.dynamoDb = DynamoDbClient.builder()
.region(Region.US_EAST_1)
.build();
}
public String createUser(String name, String email) {
String userId = UUID.randomUUID().toString();
Map<String, AttributeValue> item = new HashMap<>();
item.put("id", AttributeValue.builder().s(userId).build());
item.put("name", AttributeValue.builder().s(name).build());
item.put("email", AttributeValue.builder().s(email).build());
item.put("createdAt", AttributeValue.builder().s(Instant.now().toString()).build());
PutItemRequest request = PutItemRequest.builder()
.tableName("Users")
.item(item)
.build();
dynamoDb.putItem(request);
return userId;
}
public Map<String, AttributeValue> getUser(String userId) {
Map<String, AttributeValue> key = new HashMap<>();
key.put("id", AttributeValue.builder().s(userId).build());
GetItemRequest request = GetItemRequest.builder()
.tableName("Users")
.key(key)
.build();
GetItemResponse response = dynamoDb.getItem(request);
return response.item();
}
}
Table Design Patterns
Single table design with UUIDs:
javascript
// Single table design with UUID-based keys
const singleTableDesign = {
TableName: 'AppData',
KeySchema: [
{ AttributeName: 'PK', KeyType: 'HASH' },
{ AttributeName: 'SK', KeyType: 'RANGE' }
],
AttributeDefinitions: [
{ AttributeName: 'PK', AttributeType: 'S' },
{ AttributeName: 'SK', AttributeType: 'S' }
]
};
// Entity patterns with UUIDs
class SingleTableService {
// User entity
async createUser(name, email) {
const userId = uuidv4();
const item = {
PK: `USER#${userId}`,
SK: `USER#${userId}`,
EntityType: 'User',
id: userId,
name,
email,
createdAt: new Date().toISOString()
};
await docClient.send(new PutCommand({
TableName: 'AppData',
Item: item
}));
return userId;
}
// Order entity
async createOrder(userId, items, total) {
const orderId = uuidv4();
const item = {
PK: `USER#${userId}`,
SK: `ORDER#${orderId}`,
EntityType: 'Order',
orderId,
userId,
items,
total,
status: 'pending',
createdAt: new Date().toISOString()
};
await docClient.send(new PutCommand({
TableName: 'AppData',
Item: item
}));
return orderId;
}
// Get user with orders
async getUserWithOrders(userId) {
const result = await docClient.send(new QueryCommand({
TableName: 'AppData',
KeyConditionExpression: 'PK = :pk',
ExpressionAttributeValues: {
':pk': `USER#${userId}`
}
}));
return result.Items;
}
}
Time-series data with UUIDs:
javascript
// Time-series table with UUID partition and time-based sort
class TimeSeriesService {
async recordMetric(deviceId, metricType, value) {
const recordId = uuidv1(); // Time-based UUID for chronological ordering
const item = {
deviceId,
recordId,
metricType,
value,
timestamp: new Date().toISOString(),
ttl: Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60) // 30 days TTL
};
await docClient.send(new PutCommand({
TableName: 'Metrics',
Item: item
}));
return recordId;
}
async getRecentMetrics(deviceId, hours = 24) {
const result = await docClient.send(new QueryCommand({
TableName: 'Metrics',
KeyConditionExpression: 'deviceId = :deviceId',
FilterExpression: '#timestamp > :since',
ExpressionAttributeNames: {
'#timestamp': 'timestamp'
},
ExpressionAttributeValues: {
':deviceId': deviceId,
':since': new Date(Date.now() - hours * 60 * 60 * 1000).toISOString()
},
ScanIndexForward: false
}));
return result.Items;
}
}
Lambda Integration
Serverless UUID generation:
javascript
// AWS Lambda function with UUID generation
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { v4 as uuidv4 } from 'uuid';
const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
export const handler = async (event) => {
try {
const { name, email } = JSON.parse(event.body);
// Generate UUID for new user
const userId = uuidv4();
const requestId = uuidv4(); // For request tracking
const item = {
id: userId,
name,
email,
requestId,
createdAt: new Date().toISOString(),
source: 'lambda'
};
await docClient.send(new PutCommand({
TableName: process.env.USERS_TABLE,
Item: item
}));
return {
statusCode: 201,
headers: {
'Content-Type': 'application/json',
'X-Request-ID': requestId
},
body: JSON.stringify({
userId,
message: 'User created successfully'
})
};
} catch (error) {
console.error('Error:', error);
return {
statusCode: 500,
body: JSON.stringify({ error: 'Internal server error' })
};
}
};
Step Functions with UUID correlation:
javascript
// Step Function state machine with UUID tracking
const stepFunctionDefinition = {
Comment: "User registration workflow with UUID tracking",
StartAt: "GenerateUserId",
States: {
GenerateUserId: {
Type: "Pass",
Parameters: {
"userId.$": "States.UUID()",
"workflowId.$": "States.UUID()",
"input.$": "$"
},
Next: "CreateUser"
},
CreateUser: {
Type: "Task",
Resource: "arn:aws:lambda:us-east-1:123456789012:function:CreateUser",
Next: "SendWelcomeEmail"
},
SendWelcomeEmail: {
Type: "Task",
Resource: "arn:aws:lambda:us-east-1:123456789012:function:SendEmail",
End: true
}
}
};
Performance Optimization
UUID distribution and hot partitions:
javascript
// Good: Random UUIDs distribute evenly
class OptimizedService {
async createUser(name, email) {
const userId = uuidv4(); // Random distribution
// Store user data...
}
// Avoid: Sequential UUIDs can create hot partitions
// Don't use timestamp-based prefixes like "2024-01-01-uuid"
// Good: Use UUID with random prefix for time-series
async createTimeSeriesRecord(data) {
const recordId = `${uuidv4()}-${Date.now()}`;
// This provides both uniqueness and some time ordering
}
}
Batch operations with UUIDs:
javascript
// Batch write with UUIDs
class BatchService {
async createMultipleUsers(users) {
const items = users.map(user => ({
PutRequest: {
Item: {
id: uuidv4(),
...user,
createdAt: new Date().toISOString()
}
}
}));
// DynamoDB batch write (max 25 items)
const chunks = this.chunkArray(items, 25);
for (const chunk of chunks) {
await docClient.send(new BatchWriteCommand({
RequestItems: {
'Users': chunk
}
}));
}
}
chunkArray(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
}
Global Tables and Multi-Region
UUID considerations for Global Tables:
javascript
// UUIDs work perfectly with DynamoDB Global Tables
class GlobalService {
constructor(region) {
this.client = new DynamoDBClient({ region });
this.docClient = DynamoDBDocumentClient.from(this.client);
}
async createGlobalUser(name, email) {
const userId = uuidv4(); // Globally unique across all regions
const item = {
id: userId,
name,
email,
region: process.env.AWS_REGION,
createdAt: new Date().toISOString()
};
await this.docClient.send(new PutCommand({
TableName: 'GlobalUsers',
Item: item
}));
return userId;
}
// Cross-region replication happens automatically
// UUIDs ensure no conflicts between regions
}
Monitoring and Troubleshooting
CloudWatch metrics for UUID-based tables:
javascript
// Custom metrics for UUID operations
import { CloudWatchClient, PutMetricDataCommand } from '@aws-sdk/client-cloudwatch';
class MetricsService {
constructor() {
this.cloudwatch = new CloudWatchClient({});
}
async recordUUIDGeneration(tableName, operation) {
await this.cloudwatch.send(new PutMetricDataCommand({
Namespace: 'DynamoDB/UUID',
MetricData: [{
MetricName: 'UUIDOperations',
Dimensions: [{
Name: 'TableName',
Value: tableName
}, {
Name: 'Operation',
Value: operation
}],
Value: 1,
Unit: 'Count',
Timestamp: new Date()
}]
}));
}
}
UUID Version Comparison
Choose the right UUID version for your DynamoDB application:
- Version 1 - Time-based, good for sort keys requiring chronological order
- Version 3 - MD5 namespace-based, deterministic for consistent keys
- Version 4 - Random, excellent for partition keys and general use
- Version 5 - SHA-1 namespace-based, more secure than v3
- Version 6 - Time-ordered, better than v1 for sort keys
- Version 7 - Modern time-based, best for time-series sort keys
For DynamoDB applications:
- Partition keys: Use Version 4 for even distribution
- Sort keys: Use Version 1 or Version 7 for time ordering
- Serverless apps: Use Version 4 for Lambda functions
- IoT applications: Use Version 7 for time-series data
How do I generate UUID in other databases?
SQL databases:
- PostgreSQL - Comprehensive UUID support with extensions
- MySQL - Built-in UUID() function
- SQL Server - NEWID() and NEWSEQUENTIALID()
- SQLite - Custom functions and extensions
- Oracle - SYS_GUID() function
NoSQL databases: