Specialized skill for designing AWS DynamoDB single-table schemas with optimized access patterns. Use when modeling data, designing table structure, or optimizing DynamoDB queries for production applications.
View on GitHubswapkats/robin
robin
January 20, 2026
Select agents to install to:
npx add-skill https://github.com/swapkats/robin/blob/main/skills/designing-dynamodb-tables/SKILL.md -a claude-code --skill designing-dynamodb-tablesInstallation paths:
.claude/skills/designing-dynamodb-tables/# Designing DynamoDB Tables
You are an expert in designing production-ready DynamoDB single-table schemas optimized for performance, cost, and scalability.
## Core Principle: Single-Table Design
ONE table per application. Always. No exceptions.
### Why Single-Table?
- Reduces cross-table joins (impossible in DynamoDB anyway)
- Minimizes costs (fewer tables, consolidated throughput)
- Simplifies queries (related data co-located)
- Better performance (fetch multiple entity types in one query)
## Table Structure
### Primary Key
```
Partition Key (PK): STRING
Sort Key (SK): STRING
```
Always use generic names `PK` and `SK`. This allows flexibility for any entity type.
### Attributes
```
PK STRING (Partition Key)
SK STRING (Sort Key)
EntityType STRING (e.g., "User", "Post", "Comment")
GSI1PK STRING (GSI #1 Partition Key)
GSI1SK STRING (GSI #1 Sort Key)
GSI2PK STRING (GSI #2 Partition Key) [optional]
GSI2SK STRING (GSI #2 Sort Key) [optional]
...entity-specific attributes...
CreatedAt STRING (ISO 8601 timestamp)
UpdatedAt STRING (ISO 8601 timestamp)
```
## Entity Patterns
### User Entity
**Access Patterns:**
1. Get user by ID
2. Get user by email
3. List all users (admin only, paginated)
**Design:**
```
User Item:
PK: USER#<userId>
SK: PROFILE
EntityType: User
GSI1PK: USER#<email>
GSI1SK: USER#<email>
Email: user@example.com
Name: John Doe
CreatedAt: 2024-01-01T00:00:00Z
UpdatedAt: 2024-01-01T00:00:00Z
```
**Queries:**
```typescript
// Get user by ID
const user = await docClient.get({
TableName: TABLE_NAME,
Key: {
PK: `USER#${userId}`,
SK: 'PROFILE',
},
});
// Get user by email (using GSI1)
const user = await docClient.query({
TableName: TABLE_NAME,
IndexName: 'GSI1',
KeyConditionExpression: 'GSI1PK = :email',
ExpressionAttributeValues: {
':email': `USER#${email}`,
},
});
```
### One-to-Many Relationships
**Example: User has many Posts**
**A