AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Db Sculptor

skill-eliasoulkadi-shokunin-db-sculptor · by EliasOulkadi

Design database schemas with Prisma/Drizzle, PostgreSQL index strategy (B-tree, GIN, GiST, BRIN, Hash), query optimization (EXPLAIN ANALYZE), migration safety (expand/contract, zero-downtime), and sharding/partitioning. Use when user asks to design schema, create migrations, optimize slow queries, add indexes, choose between SQL/NoSQL, or set up Prisma/Drizzle. Do NOT use for data warehouse dimen…

No reviews yet
0 installs
23 views
0.0% view→install

Install

$ agentstack add skill-eliasoulkadi-shokunin-db-sculptor

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-eliasoulkadi-shokunin-db-sculptor)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Db Sculptor? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

DB Sculptor

Design performant database schemas. Model for access patterns first, normalize later. Based on PostgreSQL internals, Prisma/Drizzle best practices, and production patterns from PlanetScale, Neon, and pganalyze.

Sub-Commands

| Command | Description | |---------|-------------| | design | Design a schema from access patterns and data volume estimates | | index | Analyze queries and recommend/create optimal indexes | | optimize | Diagnose slow queries with EXPLAIN ANALYZE and fix them | | migrate | Create a safe, zero-downtime migration (expand/contract) | | audit | Audit existing schema against best practices and anti-patterns |

Workflow

Step 1: Model for access patterns

| Question | Determine | |----------|-----------| | Read/write ratio? | How many indexes can the table support | | Data volume? | Current rows, growth rate/month | | Consistency requirements? | ACID vs eventual, read replicas OK? | | Latency budget? | p50 100000 ORDER BY id LIMIT 20;

-- Pattern 6: Unused indexes bloating writes -- Identify unused indexes: SELECT schemaname, tablename, indexname, idxscan FROM pgstatuserindexes WHERE idxscan = 0 ORDER BY pgrelation_size(indexrelid) DESC;

-- Pattern 7: Parallel query for large scans -- Force parallel workers on large analytical queries: SET maxparallelworkerspergather = 4; EXPLAIN (ANALYZE, BUFFERS) SELECT ...;


### Step 5: Safe migrations (expand/contract)

**Prisma example:**
```prisma
// prisma/schema.prisma
model User {
  id        String   @id @default(uuid()) @db.Uuid
  email     String   @unique
  timezone  String?  // Phase 1: nullable
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  @@index([email])
  @@map("users")
}

Drizzle ORM example:

// db/schema/users.ts
import { pgTable, text, timestamp, uuid, index } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: uuid("id").defaultRandom().primaryKey(),
  email: text("email").notNull().unique(),
  timezone: text("timezone"), // Phase 1: nullable
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
}, (table) => ({
  emailIdx: index("idx_users_email").on(table.email),
}));

// Migration command: npx drizzle-kit generate && npx drizzle-kit migrate

Expand/contract SQL:

-- Phase 1 (expand): Add column as nullable
ALTER TABLE users ADD COLUMN timezone text;

-- Phase 2 (backfill): Fill data in separate deployment
UPDATE users SET timezone = 'UTC' WHERE timezone IS NULL;

-- Phase 3 (contract): Make NOT NULL, clean up
ALTER TABLE users ALTER COLUMN timezone SET NOT NULL;

-- Phase 4 (future): Drop old column
ALTER TABLE users DROP COLUMN old_timezone;

Safety rules:

  • CREATE INDEX CONCURRENTLY — never blocks writes
  • lock_timeout = '5s' on migration connections
  • One logical change per migration file
  • Backfill in separate migration from schema change
  • Rollback written BEFORE applying forward
  • Never rename + change type in same migration

PgBouncer connection pooling

# pgbouncer.ini
[databases]
mydb = host=localhost port=5432 dbname=mydb

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
default_pool_size = 25
max_client_conn = 200
max_db_connections = 25

Rules:

  • Use pool_mode = transaction (default) for most workloads — session-level pooling breaks SET and LISTEN/NOTIFY
  • Use pool_mode = session only when you need prepared statements, SET session variables, or listen/notify
  • Set max_db_connections to 25-50% of PostgreSQL max_connections — PgBouncer multiplexes client connections
  • Set default_pool_size based on CPU cores: 4× cores for mixed workloads, 1× for CPU-bound
  • Never use pool_mode = statement — breaks multi-statement transactions

Error Handling

| Scenario | Cause | Fix | |----------|-------|-----| | Migration lock timeout | Long-running query on same table | Set lock_timeout = '5s'. Run in low-traffic window. | | Query slow in prod, fast in dev | Different data volume and distribution | Test with prod-size data (~1M+ rows) in staging | | CREATE INDEX blocks writes | Non-concurrent CREATE | Always use CREATE INDEX CONCURRENTLY | | N+1 queries | ORM lazy loading | Use eager loading (include/JOIN), DataLoader, or batch queries | | Sequence gap on PK | ROLLBACK increments sequence | Accept gaps. Switch to UUIDv7 for new tables. | | Deadlock | Conflicting lock order across transactions | Ensure consistent lock ordering. Keep transactions short. |

Production Checklist

  • [ ] Primary key: UUIDv7 or bigint. Never expose sequential PKs in URLs.
  • [ ] created_at + updated_at on every table. updated_at auto-set via trigger.
  • [ ] Indexes match WHERE + ORDER BY + JOIN columns. Verified with EXPLAIN ANALYZE.
  • [ ] Composite indexes ordered by selectivity (most selective first)
  • [ ] Partial indexes for common filtered queries
  • [ ] Covering indexes (INCLUDE) for read-heavy lookups
  • [ ] lock_timeout = '5s' on migration connections
  • [ ] Migrations tested on staging with production-like data volume
  • [ ] Connection pooling configured (PgBouncer for PostgreSQL)
  • [ ] TEXT over VARCHAR(n) — no arbitrary length limits
  • [ ] TIMESTAMPTZ over TIMESTAMP — always store with timezone
  • [ ] FKs indexed — mandatory for join performance
  • [ ] Soft deletes via deleted_at TIMESTAMPTZ (nullable)

Anti-Patterns

| Anti-pattern | Fix | |-------------|-----| | No primary key | Every table needs one (UUIDv7 preferred) | | Index on every column | Max 3-4 per write-heavy table. Check usage with pg_stat_user_indexes. | | SELECT * in application code | Name explicit columns. Avoids breaking changes + unnecessary data transfer. | | Functions on indexed columns (WHERE LOWER(email) = ...) | Use expression index: CREATE INDEX ON users (LOWER(email)) | | VARCHAR(255) on all strings | TEXT unless max length is a business rule | | Migrations without testing | Test against prod copy (anonymized). Never just run on dev. | | ENUM type for evolving values | TEXT with CHECK constraint or reference table | | Missing FK indexes | Every FK column needs an index for join performance | | Sorting by unindexed column on large tables | Add composite index with sort column last | | COUNT(*) on large tables without WHERE | Use estimates: SELECT reltuples FROM pg_class WHERE relname = 'table' |

Sources

  • PostgreSQL docs (postgresql.org/docs)
  • Use the Index, Luke! (use-the-index-luke.com)
  • pganalyze EXPLAIN analyzer
  • Prisma migration docs
  • Drizzle ORM docs
  • PlanetScale schema migration patterns
  • Stormatics — composite and partial indexes
  • Neon serverless PostgreSQL patterns

Checklist

  • [ ] Skill loads without errors in the AI agent
  • [ ] YAML frontmatter is valid (description, compatibility, audience)
  • [ ] Workflow section provides clear step-by-step instructions
  • [ ] Error handling section covers common failure modes
  • [ ] All referenced files (references/, scripts/, assets/) exist
  • [ ] Skill triggers correctly for intended use cases
  • [ ] No broken links or missing resources

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.