Agent skill

DynamoDB

Use DynamoDB for serverless NoSQL database with automatic scaling, high performance, and pay-per-use pricing.

Stars 10
Forks 1

Install this agent skill to your Project

npx add-skill https://github.com/hivellm/rulebook/tree/main/templates/skills/services/dynamodb

SKILL.md

AWS DynamoDB Instructions

CRITICAL: Use DynamoDB for serverless NoSQL database with automatic scaling, high performance, and pay-per-use pricing.

Core Features

Connection

typescript
// Using @aws-sdk/client-dynamodb
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { DynamoDBDocumentClient, PutCommand, GetCommand, QueryCommand, ScanCommand } from '@aws-sdk/lib-dynamodb'

const client = new DynamoDBClient({
  region: process.env.AWS_REGION || 'us-east-1',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID || '',
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || '',
  },
})

const docClient = DynamoDBDocumentClient.from(client)

// Using AWS SDK v2
import AWS from 'aws-sdk'

const dynamodb = new AWS.DynamoDB.DocumentClient({
  region: process.env.AWS_REGION || 'us-east-1',
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
})

Basic Operations

typescript
// Put item
await docClient.send(new PutCommand({
  TableName: 'Users',
  Item: {
    id: 'user-1',
    email: 'john@example.com',
    name: 'John Doe',
    createdAt: new Date().toISOString(),
  },
}))

// Get item
const result = await docClient.send(new GetCommand({
  TableName: 'Users',
  Key: {
    id: 'user-1',
  },
}))
const user = result.Item

// Update item
await docClient.send(new UpdateCommand({
  TableName: 'Users',
  Key: { id: 'user-1' },
  UpdateExpression: 'SET #name = :name, updatedAt = :updatedAt',
  ExpressionAttributeNames: {
    '#name': 'name',
  },
  ExpressionAttributeValues: {
    ':name': 'Jane Doe',
    ':updatedAt': new Date().toISOString(),
  },
}))

// Delete item
await docClient.send(new DeleteCommand({
  TableName: 'Users',
  Key: { id: 'user-1' },
}))

Query Operations

typescript
// Query by partition key
const result = await docClient.send(new QueryCommand({
  TableName: 'Posts',
  KeyConditionExpression: 'userId = :userId',
  ExpressionAttributeValues: {
    ':userId': 'user-1',
  },
  ScanIndexForward: false, // Sort descending
  Limit: 10,
}))

// Query with GSI (Global Secondary Index)
const result = await docClient.send(new QueryCommand({
  TableName: 'Users',
  IndexName: 'EmailIndex',
  KeyConditionExpression: 'email = :email',
  ExpressionAttributeValues: {
    ':email': 'john@example.com',
  },
}))

// Scan (use sparingly)
const result = await docClient.send(new ScanCommand({
  TableName: 'Users',
  FilterExpression: '#status = :status',
  ExpressionAttributeNames: {
    '#status': 'status',
  },
  ExpressionAttributeValues: {
    ':status': 'active',
  },
  Limit: 100,
}))

Advanced Features

typescript
// Batch operations
import { BatchWriteCommand } from '@aws-sdk/lib-dynamodb'

await docClient.send(new BatchWriteCommand({
  RequestItems: {
    Users: [
      {
        PutRequest: {
          Item: { id: 'user-1', name: 'User 1' },
        },
      },
      {
        PutRequest: {
          Item: { id: 'user-2', name: 'User 2' },
        },
      },
    ],
  },
}))

// Transactions
import { TransactWriteCommand } from '@aws-sdk/lib-dynamodb'

await docClient.send(new TransactWriteCommand({
  TransactItems: [
    {
      Put: {
        TableName: 'Accounts',
        Item: { userId: 'user-1', balance: 1000 },
      },
    },
    {
      Put: {
        TableName: 'Transactions',
        Item: { id: 'tx-1', userId: 'user-1', amount: 1000 },
      },
    },
  ],
}))

// Conditional writes
await docClient.send(new PutCommand({
  TableName: 'Users',
  Item: { id: 'user-1', email: 'john@example.com' },
  ConditionExpression: 'attribute_not_exists(id)',
}))

Common Patterns

Single Table Design

typescript
// Store different entity types in one table
await docClient.send(new PutCommand({
  TableName: 'AppData',
  Item: {
    PK: 'USER#user-1',
    SK: 'METADATA',
    EntityType: 'User',
    email: 'john@example.com',
    name: 'John Doe',
  },
}))

await docClient.send(new PutCommand({
  TableName: 'AppData',
  Item: {
    PK: 'USER#user-1',
    SK: 'POST#post-1',
    EntityType: 'Post',
    title: 'My Post',
    content: 'Content here',
  },
}))

// Query all posts for a user
const result = await docClient.send(new QueryCommand({
  TableName: 'AppData',
  KeyConditionExpression: 'PK = :pk AND begins_with(SK, :sk)',
  ExpressionAttributeValues: {
    ':pk': 'USER#user-1',
    ':sk': 'POST#',
  },
}))

Time-to-Live (TTL)

typescript
// Items automatically deleted after TTL
await docClient.send(new PutCommand({
  TableName: 'Sessions',
  Item: {
    sessionId: 'session-1',
    userId: 'user-1',
    ttl: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
  },
}))

Best Practices

DO:

  • Design for access patterns
  • Use appropriate partition keys
  • Create GSIs for alternative access patterns
  • Use batch operations when possible
  • Implement exponential backoff for throttling
  • Use TTL for temporary data
  • Monitor provisioned capacity
  • Use transactions for atomic operations
  • Implement proper error handling
  • Use single table design when appropriate

DON'T:

  • Use Scan for frequent queries
  • Create too many GSIs (affects write performance)
  • Store large items (> 400KB)
  • Ignore throttling errors
  • Hardcode table names
  • Skip error handling
  • Use eventually consistent reads when strong consistency needed
  • Ignore capacity planning
  • Store sensitive data without encryption
  • Skip monitoring

Configuration

Environment Variables

bash
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
DYNAMODB_TABLE_PREFIX=myapp_

IAM Policy

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:UpdateItem",
        "dynamodb:DeleteItem",
        "dynamodb:Query",
        "dynamodb:Scan"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/myapp-*"
    }
  ]
}

Integration with Development

Testing

typescript
// Use DynamoDB Local
const localClient = new DynamoDBClient({
  endpoint: 'http://localhost:8000',
  region: 'local',
  credentials: {
    accessKeyId: 'local',
    secretAccessKey: 'local',
  },
})

// Clean up after tests
afterEach(async () => {
  // Delete test items or use separate test table
})

Health Checks

typescript
async function checkDynamoDBHealth(): Promise<boolean> {
  try {
    await docClient.send(new GetCommand({
      TableName: 'HealthCheck',
      Key: { id: 'health' },
    }))
    return true
  } catch {
    return false
  }
}

Didn't find tool you were looking for?

Be as detailed as possible for better results