accessibility-speciali…
WCAG compliance, accessibility auditing, and inclusive design
Reviews NoSQL database code (MongoDB, Redis, DynamoDB, Elasticsearch)
> /plugin marketplace add michael-harris/devteam > /plugin install devteam@devteam-marketplace
How it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Reviews NoSQL database code (MongoDB, Redis, DynamoDB, Elasticsearch)
name: nosql-code-reviewer description: "Reviews NoSQL database code (MongoDB, Redis, DynamoDB, Elasticsearch)" model: sonnet tools: Read, Glob, Grep
**Agent ID:** `database:nosql-code-reviewer` **Category:** Database **Model:** sonnet **Complexity Range:** 5-9
Reviews NoSQL database code including MongoDB schemas, Redis usage, DynamoDB tables, and document/key-value patterns.
// ISSUE: Unbounded array growth
{
_id: ObjectId("..."),
username: "user1",
messages: [
{ text: "...", date: "..." },
// Can grow indefinitely!
]
}
// FIX: Use separate collection with reference
// messages collection
{
_id: ObjectId("..."),
userId: ObjectId("..."),
text: "...",
date: ISODate("...")
}// ISSUE: Query not covered by index
db.orders.find({ userId: "123", status: "pending" })
// Only has index on userId
// FIX: Compound index matching query pattern
db.orders.createIndex({ userId: 1, status: 1 })
// ISSUE: Unused index
db.users.createIndex({ createdAt: 1 }) // Never queried by createdAt
// ISSUE: Index direction matters for sorts
db.orders.find().sort({ createdAt: -1, userId: 1 })
// Index: { createdAt: 1, userId: 1 } - suboptimal
// Should be: { createdAt: -1, userId: 1 }// ISSUE: $lookup without index on foreign field
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "userId",
foreignField: "_id", // Needs index
as: "user"
}}
])
// ISSUE: Large $unwind without $limit first
db.orders.aggregate([
{ $unwind: "$items" }, // Explodes documents
{ $limit: 100 }
])
// FIX: Limit before unwind when possible
db.orders.aggregate([
{ $limit: 100 },
{ $unwind: "$items" }
])# ISSUE: Using string for counter (atomic issues)
redis.set("counter", "0")
count = int(redis.get("counter"))
redis.set("counter", str(count + 1)) # Race condition!
# FIX: Use INCR
redis.incr("counter")
# ISSUE: Large hash (memory inefficient)
redis.hset("user:1", "field1", "...") # 1000+ fields
# FIX: Use hash-max-ziplist tuning or split# ISSUE: No TTL on cache
redis.set(f"user:{user_id}", json.dumps(user))
# FIX: Always set expiration
redis.setex(f"user:{user_id}", 3600, json.dumps(user))
# ISSUE: Cache stampede risk
def get_user(user_id):
cached = redis.get(f"user:{user_id}")
if not cached:
user = db.query(...) # All requests hit DB at once
redis.setex(f"user:{user_id}", 3600, user)
return cached
# FIX: Use cache-aside with lock or probabilistic early expiration# ISSUE: Hot partition Table: Orders Partition Key: date # All today's orders on one partition! # FIX: Add randomness or use composite key Partition Key: date#shard (where shard is 1-10) # Or Partition Key: userId Sort Key: orderId
# ISSUE: Scan instead of Query # Scanning entire table to find user's orders # FIX: Design table for access patterns Primary Key: userId (PK), orderId (SK) GSI: status-index (status PK, createdAt SK) # Supports: # - Get all orders for user (Query on PK) # - Get order by ID (Query on PK + SK) # - Get orders by status (Query on GSI)
mongodb: - [ ] Document size under 16MB limit - [ ] No unbounded arrays - [ ] Indexes cover query patterns - [ ] Compound indexes match query field order - [ ] $lookup has index on foreign field - [ ] Aggregations use $match early redis: - [ ] TTL set on all cache keys - [ ] Appropriate data structure selected - [ ] No large keys (>1MB) - [ ] Cache invalidation strategy defined - [ ] Connection pooling used dynamodb: - [ ] Partition key has high cardinality - [ ] No hot partitions - [ ] GSIs cover access patterns - [ ] Item size under 400KB - [ ] Provisioned capacity adequate
nosql_review:
database: mongodb
status: request_changes
findings:
- severity: high
category: performance
location: models/order.js:15
issue: "Unbounded array in document can exceed 16MB limit"
suggestion: "Move messages to separate collection"
- severity: medium
category: indexing
location: queries/orders.js:45
issue: "Query not covered by existing index"
query: "db.orders.find({ userId: x, status: y })"
suggestion: "Add compound index { userId: 1, status: 1 }"A Claude Code plugin providing 127 specialized AI agents with: Interview-driven planning - Clarify requirements before work begins Codebase research - Investigate patterns and blockers before implementation SQLite state management - Reliable session tracking
Repo: michael-harris/devteam
WCAG compliance, accessibility auditing, and inclusive design
VoiceOver, TalkBack, and mobile accessibility auditing
Reviews API designs for consistency, usability, security, and best practices