
database-expert
Advanced database design and administration for PostgreSQL, MongoDB, and Redis. Use when designing schemas, optimizing queries, managing database performance, or implementing data patterns.
- Installs
- 249
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/travisjneuman/.claude --skill database-expert- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads database-expert automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Database Expert
Comprehensive guide for database design, optimization, and administration.
Database Selection
| Database | Type | Best For |
|---|---|---|
| PostgreSQL | Relational | Complex queries, ACID, JSON support |
| MongoDB | Document | Flexible schemas, rapid iteration |
| Redis | Key-Value | Caching, sessions, real-time |
| SQLite | Embedded | Mobile, desktop, testing |
PostgreSQL
Schema Design
-- Users table with proper constraints
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
full_name VARCHAR(100) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'active'
CHECK (status IN ('active', 'inactive', 'suspended')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Index for common queries
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status) WHERE status = 'active';
-- Automatic updated_at trigger
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- Posts with full-text search
CREATE TABLE posts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
author_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
tags TEXT[] DEFAULT '{}',
search_vector TSVECTOR,
published_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Full-text search index
CREATE INDEX idx_posts_search ON posts USING GIN(search_vector);
Query Optimization
-- EXPLAIN ANALYZE for query analysis
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT u.full_name, COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
WHERE u.status = 'active'
GROUP BY u.id
ORDER BY post_count DESC
LIMIT 10;
-- Partial index for filtered queries
CREATE INDEX idx_posts_published
ON posts(published_at)
WHERE published_at IS NOT NULL;
-- Covering index (index-only scan)
CREATE INDEX idx_posts_author_title
ON posts(author_id)
INCLUDE (title, published_at);
-- Expression index
CREATE INDEX idx_users_email_lower
ON users(LOWER(email));
Advanced Features
-- Common Table Expression (CTE)
WITH active_authors AS (
SELECT DISTINCT author_id
FROM posts
WHERE published_at > NOW() - INTERVAL '30 days'
),
author_stats AS (
SELECT
u.id,
u.full_name,
COUNT(p.id) as total_posts
FROM users u
JOIN active_authors aa ON aa.author_id = u.id
LEFT JOIN posts p ON p.author_id = u.id
GROUP BY u.id
)
SELECT * FROM author_stats
ORDER BY total_posts DESC;
-- Window functions
SELECT
id,
title,
author_id,
published_at,
ROW_NUMBER() OVER (PARTITION BY author_id ORDER BY published_at DESC) as author_rank,
LAG(published_at) OVER (PARTITION BY author_id ORDER BY published_at) as prev_post_date
FROM posts
WHERE published_at IS NOT NULL;
-- JSON operations
SELECT
id,
metadata->>'source' as source,
metadata->'stats'->>'views' as views
FROM posts
WHERE metadata @> '{"featured": true}';
-- Recursive CTE (for hierarchies)
WITH RECURSIVE category_tree AS (
SELECT id, name, parent_id, 0 as depth
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, ct.depth + 1
FROM categories c
JOIN category_tree ct ON c.parent_id = ct.id
WHERE ct.depth < 10
)
SELECT * FROM category_tree ORDER BY depth;
MongoDB
Schema Design Patterns
// Embedding (for 1:few relationships)
const userSchema = {
_id: ObjectId,
email: String,
profile: {
firstName: String,
lastName: String,
avatar: String,
},
addresses: [
{
type: String,
street: String,
city: String,
},
],
};
// Referencing (for 1:many relationships)
const postSchema = {
_id: ObjectId,
authorId: ObjectId,
title: String,
content: String,
tags: [String],
};
Aggregation Pipeline
// Complex aggregation
db.orders.aggregate([
{
$match: {
status: "completed",
createdAt: { $gte: ISODate("2024-01-01") },
},
},
{
$lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user",
},
},
{ $unwind: "$user" },
{
$group: {
_id: { month: { $month: "$createdAt" } },
totalRevenue: { $sum: "$total" },
orderCount: { $sum: 1 },
},
},
{ $sort: { totalRevenue: -1 } },
]);
Indexes
// Compound index
db.posts.createIndex({ authorId: 1, createdAt: -1 });
// Text index
db.posts.createIndex(
{ title: "text", content: "text" },
{ weights: { title: 10, content: 1 } },
);
// Partial index
db.orders.createIndex(
{ createdAt: 1 },
{ partialFilterExpression: { status: "pending" } },
);
// TTL index (auto-expire)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
Redis
Data Structures
# Strings
SET user:1:name "John Doe"
GET user:1:name
SETEX session:abc123 3600 "user_data"
INCR page:home:views
# Hashes
HSET user:1 name "John" email "john@example.com"
HGETALL user:1
# Lists (queues)
LPUSH queue:jobs '{"type":"email"}'
RPOP queue:jobs
# Sets
SADD user:1:roles admin editor
SISMEMBER user:1:roles admin
# Sorted Sets (leaderboards)
ZADD leaderboard 1000 "player1" 1500 "player2"
ZREVRANGE leaderboard 0 9 WITHSCORES
# Streams (event log)
XADD events * type "user_login" user_id "123"
XREAD COUNT 10 STREAMS events 0
Caching Patterns
// Cache-aside pattern
async function getUser(userId: string): Promise<User> {
const cacheKey = `user:${userId}`;
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const user = await db.users.findById(userId);
await redis.setex(cacheKey, 3600, JSON.stringify(user));
return user;
}
// Rate limiting
async function checkRateLimit(
userId: string,
limit: number,
window: number,
): Promise<boolean> {
const key = `ratelimit:${userId}`;
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, window);
}
return current <= limit;
}
// Distributed lock
async function acquireLock(
resource: string,
ttl: number,
): Promise<string | null> {
const lockId = crypto.randomUUID();
const acquired = await redis.set(`lock:${resource}`, lockId, "NX", "EX", ttl);
return acquired ? lockId : null;
}
// Release lock with Lua script (atomic operation)
// Use EVALSHA with pre-loaded script for production
const releaseLockScript = `
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
`;
Pub/Sub
// Publisher
async function publishEvent(channel: string, event: object): Promise<void> {
await redis.publish(channel, JSON.stringify(event));
}
// Subscriber
const subscriber = redis.duplicate();
subscriber.subscribe("events");
subscriber.on("message", (channel, message) => {
const event = JSON.parse(message);
handleEvent(event);
});
Query Optimization Checklist
PostgreSQL
- Use EXPLAIN ANALYZE for slow queries
- Create indexes for WHERE, JOIN, ORDER BY columns
- Use partial indexes for filtered queries
- Use connection pooling (pgbouncer)
- Regular VACUUM and ANALYZE
MongoDB
- Create compound indexes matching query patterns
- Use covered queries when possible
- Avoid large array fields in documents
- Monitor with explain()
Redis
- Use appropriate data structures
- Set TTL on cache keys
- Use pipelining for bulk operations
- Monitor memory usage
Vector Databases for AI/RAG Workloads
Overview
Vector databases store high-dimensional embeddings and enable similarity search, which is the foundation of RAG (Retrieval-Augmented Generation) and semantic search applications.
| Database | Type | Best For |
|---|---|---|
| pgvector | PostgreSQL extension | Existing Postgres stacks, hybrid queries |
| Pinecone | Managed cloud | Production scale, serverless |
| Weaviate | Self-hosted/cloud | Multimodal, GraphQL interface |
| Chroma | Embedded/local | Prototyping, small datasets |
| Qdrant | Self-hosted/cloud | High performance, rich filtering |
| Milvus | Self-hosted/cloud | Large-scale, distributed |
pgvector (PostgreSQL Extension)
-- Enable extension
CREATE EXTENSION vector;
-- Create table with vector column
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
embedding VECTOR(1536), -- OpenAI text-embedding-3-small dimension
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Create HNSW index (faster search, more memory)
CREATE INDEX idx_documents_embedding ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Or IVFFlat index (less memory, requires training)
CREATE INDEX idx_documents_embedding_ivf ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- Similarity search (cosine distance)
SELECT id, content, metadata,
1 - (embedding <=> $1::vector) AS similarity
FROM documents
WHERE metadata @> '{"category": "technical"}' -- Combine with metadata filter
ORDER BY embedding <=> $1::vector
LIMIT 10;
-- Hybrid search: combine full-text + vector
SELECT id, content,
ts_rank(search_vector, plainto_tsquery($1)) AS text_score,
1 - (embedding <=> $2::vector) AS vector_score
FROM documents
WHERE search_vector @@ plainto_tsquery($1)
ORDER BY (0.3 * ts_rank(search_vector, plainto_tsquery($1))
+ 0.7 * (1 - (embedding <=> $2::vector))) DESC
LIMIT 10;
Pinecone (Managed)
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="xxx")
# Create index
pc.create_index(
name="documents",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
)
index = pc.Index("documents")
# Upsert with metadata
index.upsert(vectors=[
{
"id": "doc1",
"values": embedding_vector,
"metadata": {"source": "manual", "category": "faq"},
},
])
# Query with metadata filter
results = index.query(
vector=query_embedding,
top_k=5,
include_metadata=True,
filter={"category": {"$eq": "faq"}},
)
Chroma (Local/Embedded)
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(
name="documents",
metadata={"hnsw:space": "cosine"},
)
# Add documents (auto-embeds with default model)
collection.add(
documents=["Document text 1", "Document text 2"],
metadatas=[{"source": "web"}, {"source": "pdf"}],
ids=["doc1", "doc2"],
)
# Or add pre-computed embeddings
collection.add(
embeddings=[vector1, vector2],
metadatas=[{"source": "web"}, {"source": "pdf"}],
ids=["doc1", "doc2"],
)
# Query
results = collection.query(
query_texts=["search query"],
n_results=5,
where={"source": "web"},
)
Embedding Storage and Indexing Best Practices
| Consideration | Recommendation |
|---|---|
| Embedding model | text-embedding-3-small (1536d) or nomic-embed (768d) |
| Index type | HNSW for <1M vectors, IVFFlat for >1M |
| Dimensionality | Lower dims = faster search, slightly less accuracy |
| Batch inserts | Batch 100-1000 vectors per upsert call |
| Metadata | Store filterable attributes alongside vectors |
| Hybrid search | Combine keyword (BM25) + vector for best results |
| Reranking | Use cross-encoder reranker on top-k results |
| Chunking | 500-1000 tokens per chunk with 100-200 overlap |
FAQ
What does the database-expert skill do?
Advanced database design and administration for PostgreSQL, MongoDB, and Redis. Use when designing schemas, optimizing queries, managing database performance, or implementing data patterns.
How do I install database-expert?
Run npx skills add https://github.com/travisjneuman/.claude --skill database-expert in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/database-expert/ (personal) or .claude/skills/database-expert/ (project).
Which AI agents can use database-expert?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is database-expert safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains database-expert?
It is published by travisjneuman in travisjneuman/.claude. It has 249 recorded installs.
More from travisjneuman/.claude
document-skills
travisjneuman/.claude
Professional document creation, editing, and analysis for Office formats (docx, pdf, pptx, xlsx). Use when working with Word documents, PDFs, PowerPoint presentations, or Excel spreadsheets.
brand-identity
travisjneuman/.claude
Brand strategy and identity design for businesses and products. Use when creating brand guidelines, developing visual identity systems, or defining brand positioning.
travel-planner
travisjneuman/.claude
Travel destination research and daily itinerary creation with logistics planning, budget tracking, and experience optimization. Use when planning trips, creating travel itineraries, comparing destinations, or organizing travel logistics.
business-strategy
travisjneuman/.claude
Business strategy expertise for strategic planning, competitive analysis, market entry, M&A strategy, portfolio management, and strategic decision-making. Use when analyzing competitive positioning, planning growth strategies, or making strategic decisions.
graphic-design
travisjneuman/.claude
Professional graphic design principles for digital and print media. Use when creating visual designs, choosing color palettes, typography, layouts, or providing design feedback.
real-estate-analyzer
travisjneuman/.claude
Open the skill to read its SKILL.md instructions.
Popular data & databases skills
supabase-postgres-best-practices
supabase/agent-skills
Postgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill BEFORE writing or changing anything that lives in a Postgres database: creating or altering tables and columns (including choosing column types), schema design, migrations and declarative schema files, RLS policies and the tests that verify them, indexes, triggers, database functions, queues and scheduled jobs (pgcron, pgmq), vector/semantic search (pgvector), and restoring dumps (pgrestore) or importing data. Also load it when diagnosing slow queries, high CPU, timeouts, EXPLAIN plans, connection exhaustion, locking, bloat, or rows visible to the wrong user or tenant. This is not just a performance guide — schema, migration, security, and SQL authoring tasks need these rules too, even for a one-column change or a single query.
prisma-client-api
prisma/skills
Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering data, or configuring Prisma Client. Triggers on "prisma query", "findMany", "create", "update", "delete", "$transaction".
prisma-database-setup
prisma/skills
Deprecated compatibility name for prisma-orm-setup. Use only when a user or existing integration explicitly invokes prisma-database-setup; otherwise select prisma-orm-setup.
prisma-cli
prisma/skills
Prisma ORM 7 CLI reference for existing Prisma 7 applications or explicitly selected Prisma 7 workflows. Covers prisma init, generate, migrate, db, dev, studio, and mcp. For setup, connection repair, or Prisma 8, use prisma-orm-setup; not the Prisma Platform CLI.
prisma-postgres
prisma/skills
Deprecated compatibility name for prisma-postgres-setup. Use only when a user or existing integration explicitly invokes prisma-postgres; otherwise select prisma-postgres-setup.
prisma-driver-adapter-implementation
prisma/skills
Required reference for Prisma ORM 7 SQL driver adapter work. Use when implementing or modifying adapters, adding database drivers, or touching SqlDriverAdapter, Transaction, savepoint, result mapping, or DriverAdapterError behavior. Covers current transaction lifecycle, optional savepoint hooks, original database-error preservation, and verification.