From vfm-agent-company
NoSQL database expertise with MongoDB and DynamoDB from Amazon/Netflix engineers. Use when designing document schemas, optimizing MongoDB queries and indexes, configuring DynamoDB tables with GSI/LSI, implementing data modeling for flexible schemas, handling horizontal scaling, or migrating from SQL to NoSQL. Triggers on MongoDB, DynamoDB, NoSQL, document database, collection design, partition keys, or non-relational database tasks.
npx claudepluginhub duylinhdang1998/claude-template-agent --plugin vfm-agent-companyThis skill uses the workspace's default tool permissions.
**Purpose**: Design and optimize NoSQL databases for flexible schemas, horizontal scaling, and high performance
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Purpose: Design and optimize NoSQL databases for flexible schemas, horizontal scaling, and high performance
Agent: Amazon Cloud Architect / Netflix Backend Architect Use When: Building apps with flexible data models, high write throughput, or need for horizontal scaling
// User document
{
_id: ObjectId("507f1f77bcf86cd799439011"),
email: "john@example.com",
name: "John Doe",
profile: {
age: 30,
city: "NYC"
},
tags: ["developer", "nodejs"],
createdAt: ISODate("2024-01-01T00:00:00Z")
}
// Embedded vs Referenced
// ✅ Embed: One-to-few, data belongs together
{
_id: 1,
title: "Post",
comments: [
{ author: "Alice", text: "Great!" },
{ author: "Bob", text: "Thanks!" }
]
}
// ✅ Reference: One-to-many, independent entities
{
_id: 1,
title: "Post",
authorId: ObjectId("...")
}
import mongoose from 'mongoose'
const userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
name: { type: String, required: true },
profile: {
age: Number,
city: String
},
tags: [String],
createdAt: { type: Date, default: Date.now }
})
const User = mongoose.model('User', userSchema)
// Create
const user = await User.create({
email: 'john@example.com',
name: 'John Doe',
profile: { age: 30, city: 'NYC' }
})
// Find
const users = await User.find({ 'profile.city': 'NYC' })
const user = await User.findOne({ email: 'john@example.com' })
// Update
await User.updateOne(
{ _id: userId },
{ $set: { 'profile.age': 31 } }
)
// Delete
await User.deleteOne({ _id: userId })
// Aggregation
const stats = await User.aggregate([
{ $match: { 'profile.city': 'NYC' } },
{ $group: { _id: '$profile.city', count: { $sum: 1 } } }
])
// Single field
userSchema.index({ email: 1 })
// Compound index
userSchema.index({ 'profile.city': 1, createdAt: -1 })
// Text search
userSchema.index({ name: 'text', 'profile.bio': 'text' })
await User.find({ $text: { $search: 'developer nodejs' } })
// Unique index
userSchema.index({ email: 1 }, { unique: true })
// Single table design
Table: app-data
Partition Key: PK (String)
Sort Key: SK (String)
// User
PK: USER#123
SK: PROFILE
Attributes: { email, name, ... }
// User's posts
PK: USER#123
SK: POST#456
Attributes: { title, content, ... }
// Post
PK: POST#456
SK: METADATA
Attributes: { title, authorId, ... }
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import {
DynamoDBDocumentClient,
GetCommand,
PutCommand,
QueryCommand,
UpdateCommand
} from '@aws-sdk/lib-dynamodb'
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}))
const TABLE = 'app-data'
// Put item
await client.send(new PutCommand({
TableName: TABLE,
Item: {
PK: 'USER#123',
SK: 'PROFILE',
email: 'john@example.com',
name: 'John Doe'
}
}))
// Get item
const result = await client.send(new GetCommand({
TableName: TABLE,
Key: { PK: 'USER#123', SK: 'PROFILE' }
}))
// Query (same partition key)
const posts = await client.send(new QueryCommand({
TableName: TABLE,
KeyConditionExpression: 'PK = :pk AND begins_with(SK, :sk)',
ExpressionAttributeValues: {
':pk': 'USER#123',
':sk': 'POST#'
}
}))
// Update
await client.send(new UpdateCommand({
TableName: TABLE,
Key: { PK: 'USER#123', SK: 'PROFILE' },
UpdateExpression: 'SET #name = :name',
ExpressionAttributeNames: { '#name': 'name' },
ExpressionAttributeValues: { ':name': 'Jane Doe' }
}))
// Conditional update (optimistic locking)
await client.send(new UpdateCommand({
TableName: TABLE,
Key: { PK: 'USER#123', SK: 'PROFILE' },
UpdateExpression: 'SET balance = balance + :amount',
ConditionExpression: 'balance >= :min',
ExpressionAttributeValues: {
':amount': 100,
':min': 0
}
}))
// Query by email (not primary key)
GSI: EmailIndex
Partition Key: email
Sort Key: -
await client.send(new QueryCommand({
TableName: TABLE,
IndexName: 'EmailIndex',
KeyConditionExpression: 'email = :email',
ExpressionAttributeValues: {
':email': 'john@example.com'
}
}))
.explain())Remember: NoSQL trades ACID guarantees for scalability. Choose based on access patterns, not relational habits.
Created: 2026-02-04 Maintained By: Amazon Cloud Architect