Back to Skills

nosql-database-design

aj-geddes
Updated Today
24 views
7
7
View on GitHub
Designworddesigndata

About

This Claude Skill designs NoSQL database schemas for MongoDB and DynamoDB, helping developers model document structures and plan data architectures. It covers data modeling patterns, denormalization strategies, and query optimization for both document and key-value databases. Use it when designing collections, making embedding vs. referencing decisions, or optimizing NoSQL indexing strategies.

Quick Install

Claude Code

Recommended
Plugin CommandRecommended
/plugin add https://github.com/aj-geddes/useful-ai-prompts
Git CloneAlternative
git clone https://github.com/aj-geddes/useful-ai-prompts.git ~/.claude/skills/nosql-database-design

Copy and paste this command in Claude Code to install this skill

Documentation

NoSQL Database Design

Overview

Design scalable NoSQL schemas for MongoDB (document) and DynamoDB (key-value). Covers data modeling patterns, denormalization strategies, and query optimization for NoSQL systems.

When to Use

  • MongoDB collection design
  • DynamoDB table and index design
  • Document structure modeling
  • Embedding vs. referencing decisions
  • Query pattern optimization
  • NoSQL indexing strategies
  • Data denormalization planning

MongoDB Schema Design

Document Structure Design

MongoDB - Embedded Documents:

// Single document with embedded arrays
db.createCollection("users")

db.users.insertOne({
  _id: ObjectId("..."),
  email: "[email protected]",
  name: "John Doe",
  createdAt: new Date(),

  // Embedded address
  address: {
    street: "123 Main St",
    city: "New York",
    state: "NY",
    zipCode: "10001"
  },

  // Embedded array of items
  orders: [
    {
      orderId: ObjectId("..."),
      date: new Date(),
      total: 149.99
    },
    {
      orderId: ObjectId("..."),
      date: new Date(),
      total: 89.99
    }
  ]
})

MongoDB - Referenced Documents:

// Separate collections with references
db.createCollection("users")
db.createCollection("orders")

db.users.insertOne({
  _id: ObjectId("..."),
  email: "[email protected]",
  name: "John Doe"
})

db.orders.insertMany([
  {
    _id: ObjectId("..."),
    userId: ObjectId("..."),  // Reference to user
    orderDate: new Date(),
    total: 149.99
  },
  {
    _id: ObjectId("..."),
    userId: ObjectId("..."),
    orderDate: new Date(),
    total: 89.99
  }
])

// Query with $lookup for JOINs
db.orders.aggregate([
  {
    $match: { userId: ObjectId("...") }
  },
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  }
])

Indexing in MongoDB

// Single field index
db.users.createIndex({ email: 1 })
db.orders.createIndex({ createdAt: -1 })

// Compound index
db.orders.createIndex({ userId: 1, createdAt: -1 })

// Text index for search
db.products.createIndex({ name: "text", description: "text" })

// Geospatial index
db.stores.createIndex({ location: "2dsphere" })

// TTL index for auto-expiration
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// Sparse index (only documents with field)
db.users.createIndex({ phone: 1 }, { sparse: true })

// Check index usage
db.users.aggregate([{ $indexStats: {} }])

Schema Validation

// Define collection validation schema
db.createCollection("products", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["name", "price", "category"],
      properties: {
        _id: { bsonType: "objectId" },
        name: {
          bsonType: "string",
          description: "Product name (required)"
        },
        price: {
          bsonType: "decimal",
          minimum: 0,
          description: "Price must be positive"
        },
        category: {
          enum: ["electronics", "clothing", "food"],
          description: "Category must be one of listed values"
        },
        tags: {
          bsonType: "array",
          items: { bsonType: "string" }
        },
        createdAt: {
          bsonType: "date"
        }
      }
    }
  }
})

DynamoDB Schema Design

Table Structure

// DynamoDB table with single primary key
const TableName = "users"
const params = {
  TableName,
  KeySchema: [
    { AttributeName: "userId", KeyType: "HASH" }  // Partition key
  ],
  AttributeDefinitions: [
    { AttributeName: "userId", AttributeType: "S" }  // String
  ],
  BillingMode: "PAY_PER_REQUEST"  // On-demand
}

// DynamoDB table with composite primary key
const ordersParams = {
  TableName: "orders",
  KeySchema: [
    { AttributeName: "userId", KeyType: "HASH" },      // Partition key
    { AttributeName: "orderId", KeyType: "RANGE" }    // Sort key
  ],
  AttributeDefinitions: [
    { AttributeName: "userId", AttributeType: "S" },
    { AttributeName: "orderId", AttributeType: "S" }
  ],
  BillingMode: "PAY_PER_REQUEST"
}

Global Secondary Indexes (GSI)

// Add GSI for querying by email
const gsiParams = {
  TableName: "users",
  AttributeDefinitions: [
    { AttributeName: "email", AttributeType: "S" }
  ],
  GlobalSecondaryIndexes: [
    {
      IndexName: "emailIndex",
      KeySchema: [
        { AttributeName: "email", KeyType: "HASH" }
      ],
      Projection: {
        ProjectionType: "ALL"  // Return all attributes
      },
      BillingMode: "PAY_PER_REQUEST"
    }
  ]
}

// GSI with composite key for time-based queries
const timeIndexParams = {
  GlobalSecondaryIndexes: [
    {
      IndexName: "userCreatedIndex",
      KeySchema: [
        { AttributeName: "userId", KeyType: "HASH" },
        { AttributeName: "createdAt", KeyType: "RANGE" }
      ],
      Projection: { ProjectionType: "ALL" },
      BillingMode: "PAY_PER_REQUEST"
    }
  ]
}

DynamoDB Item Operations

// Put item (insert/update)
const putParams = {
  TableName: "users",
  Item: {
    userId: { S: "user-123" },
    email: { S: "[email protected]" },
    name: { S: "John Doe" },
    createdAt: { N: Date.now().toString() },
    metadata: {
      M: {
        joinDate: { N: Date.now().toString() },
        source: { S: "web" }
      }
    }
  }
}

// Query using GSI
const queryParams = {
  TableName: "users",
  IndexName: "emailIndex",
  KeyConditionExpression: "email = :email",
  ExpressionAttributeValues: {
    ":email": { S: "[email protected]" }
  }
}

// Batch get items
const batchGetParams = {
  RequestItems: {
    "users": {
      Keys: [
        { userId: { S: "user-123" } },
        { userId: { S: "user-456" } }
      ]
    }
  }
}

Denormalization Patterns

MongoDB - Embedding for Performance:

// Embed frequently accessed data to avoid lookups
db.orders.insertOne({
  _id: ObjectId("..."),
  userId: ObjectId("..."),
  userEmail: "[email protected]",      // Denormalized
  userName: "John Doe",                // Denormalized
  createdAt: new Date(),
  items: [
    {
      productId: ObjectId("..."),
      productName: "Laptop",            // Denormalized
      productPrice: 999.99,             // Denormalized
      quantity: 1
    }
  ]
})

DynamoDB - Denormalization with Consistency:

// Store related data in same item to ensure consistency
const params = {
  TableName: "orders",
  Item: {
    userId: { S: "user-123" },
    orderId: { S: "order-456" },
    orderDate: { N: Date.now().toString() },

    // User data snapshot at order time
    userSnapshot: {
      M: {
        email: { S: "[email protected]" },
        address: { S: "123 Main St" }
      }
    },

    // Items with product information
    items: {
      L: [
        {
          M: {
            productId: { S: "prod-789" },
            name: { S: "Laptop" },
            price: { N: "999.99" },
            quantity: { N: "1" }
          }
        }
      ]
    }
  }
}

Design Patterns

MongoDB - Time-Series Pattern:

// Efficient time-series data storage
db.sensor_data.insertOne({
  _id: ObjectId("..."),
  sensorId: "sensor-123",
  date: ISODate("2024-01-15"),
  measurements: [
    { time: "12:00", temperature: 72.5, humidity: 45 },
    { time: "12:01", temperature: 72.6, humidity: 45.2 },
    { time: "12:02", temperature: 72.4, humidity: 44.8 }
  ]
})

// Index for efficient queries
db.sensor_data.createIndex({ sensorId: 1, date: -1 })

DynamoDB - One-to-Many Relationship:

// Store one-to-many relationships efficiently
// User comments using userId as partition key, commentId as sort key
const commentParams = {
  TableName: "comments",
  Item: {
    userId: { S: "user-123" },           // Partition key
    commentId: { S: "comment-789" },     // Sort key
    postId: { S: "post-456" },
    content: { S: "Great article!" },
    createdAt: { N: Date.now().toString() }
  }
}

Capacity Planning

MongoDB - Horizontal Scaling:

// Sharding for large collections
sh.shardCollection("ecommerce.orders", { userId: "hashed" })

// Monitor shard distribution
db.orders.aggregate([
  { $group: { _id: "$userId", count: { $sum: 1 } } },
  { $sort: { count: -1 } }
])

DynamoDB - Partition Key Design:

// Good: Distribute across many keys
// Partition key: "USER#123" (spreads across partitions)
// Sort key: "ORDER#2024-01"

// Bad: Hot partition
// Partition key: "ADMIN" (all admin operations hit same partition)

// Solution: Add timestamp or random suffix
// Partition key: "ADMIN#20240115#random"

Migration Considerations

  • Plan data migration strategy
  • Consider consistency requirements
  • Test query patterns before finalizing schema
  • Monitor performance after deployment
  • Document relationships and access patterns
  • Plan for schema evolution

Resources

GitHub Repository

aj-geddes/useful-ai-prompts
Path: skills/nosql-database-design

Related Skills

content-collections

Meta

This skill provides a production-tested setup for Content Collections, a TypeScript-first tool that transforms Markdown/MDX files into type-safe data collections with Zod validation. Use it when building blogs, documentation sites, or content-heavy Vite + React applications to ensure type safety and automatic content validation. It covers everything from Vite plugin configuration and MDX compilation to deployment optimization and schema validation.

View skill

langchain

Meta

LangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.

View skill

Algorithmic Art Generation

Meta

This skill helps developers create algorithmic art using p5.js, focusing on generative art, computational aesthetics, and interactive visualizations. It automatically activates for topics like "generative art" or "p5.js visualization" and guides you through creating unique algorithms with features like seeded randomness, flow fields, and particle systems. Use it when you need to build reproducible, code-driven artistic patterns.

View skill

webapp-testing

Testing

This Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.

View skill