{"id":"0a029f02-023f-42d8-b29e-0b998c0f09c9","shortId":"hrRj3y","kind":"skill","title":"database-design","tagline":"Designs database schemas, indexing strategies, query optimization, and migration patterns for SQL and NoSQL databases. Use when designing tables, optimizing queries, fixing N+1 problems, planning migrations, or when asked about database performance, normalization, ORMs, or data m","description":"# Database Design\n\n### When to Load\n\n- **Trigger**: Schema design, migrations, query optimization, indexing strategies, data modeling, N+1 fixes\n- **Skip**: No database work involved in the current task\n\n## Database Design Workflow\n\nCopy this checklist and track progress:\n\n```\nDatabase Design Progress:\n- [ ] Step 1: Identify entities and relationships\n- [ ] Step 2: Normalize schema (3NF minimum)\n- [ ] Step 3: Evaluate denormalization needs\n- [ ] Step 4: Design indexes for query patterns\n- [ ] Step 5: Write and optimize critical queries\n- [ ] Step 6: Plan migration strategy\n- [ ] Step 7: Configure connection pooling\n- [ ] Step 8: Validate against anti-patterns checklist\n```\n\n## Schema Design Principles\n\n### Normalization Forms\n\n```\n1NF: Atomic values, no repeating groups\n2NF: 1NF + no partial dependencies (all non-key columns depend on full PK)\n3NF: 2NF + no transitive dependencies (non-key columns don't depend on other non-key columns)\n```\n\n```sql\n-- WRONG: Unnormalized\nCREATE TABLE orders (\n  id SERIAL PRIMARY KEY,\n  customer_name TEXT,\n  customer_email TEXT,        -- duplicated across orders\n  product1_name TEXT,         -- repeating groups\n  product1_qty INT,\n  product2_name TEXT,\n  product2_qty INT\n);\n\n-- CORRECT: Normalized to 3NF\nCREATE TABLE customers (\n  id SERIAL PRIMARY KEY,\n  name TEXT NOT NULL,\n  email TEXT UNIQUE NOT NULL\n);\n\nCREATE TABLE orders (\n  id SERIAL PRIMARY KEY,\n  customer_id INT REFERENCES customers(id),\n  created_at TIMESTAMPTZ DEFAULT NOW()\n);\n\nCREATE TABLE order_items (\n  id SERIAL PRIMARY KEY,\n  order_id INT REFERENCES orders(id),\n  product_id INT REFERENCES products(id),\n  quantity INT NOT NULL CHECK (quantity > 0)\n);\n```\n\n### When to Denormalize\n\nDenormalize only when you have measured proof of performance issues:\n\n```sql\n-- Acceptable denormalization: precomputed counter to avoid COUNT(*)\nALTER TABLE posts ADD COLUMN comment_count INT DEFAULT 0;\n\n-- Update via trigger or application code\nCREATE FUNCTION update_comment_count() RETURNS TRIGGER AS $$\nBEGIN\n  IF TG_OP = 'INSERT' THEN\n    UPDATE posts SET comment_count = comment_count + 1 WHERE id = NEW.post_id;\n  ELSIF TG_OP = 'DELETE' THEN\n    UPDATE posts SET comment_count = comment_count - 1 WHERE id = OLD.post_id;\n  END IF;\n  RETURN NULL;\nEND;\n$$ LANGUAGE plpgsql;\n```\n\n## Indexing Strategy\n\n### Index Types and When to Use\n\n```\nB-tree (default):  Equality, range, sorting, LIKE 'prefix%'\nHash:              Equality only (rarely better than B-tree)\nGIN:               Full-text search, JSONB, arrays\nGiST:              Geometry, range types, full-text\nBRIN:              Large tables with naturally ordered data (timestamps)\n```\n\n### Composite Indexes\n\n```sql\n-- Column order matters: leftmost prefix rule\nCREATE INDEX idx_users_status_created ON users (status, created_at);\n\n-- This index supports:\n--   WHERE status = 'active'                          -- YES\n--   WHERE status = 'active' AND created_at > '2024'  -- YES\n--   WHERE created_at > '2024'                        -- NO (skips first column)\n```\n\n### Partial and Covering Indexes\n\n```sql\n-- Partial index: only index rows matching condition\nCREATE INDEX idx_orders_pending ON orders (created_at)\n  WHERE status = 'pending';  -- smaller index, faster lookups\n\n-- Covering index: include columns to avoid table lookup\nCREATE INDEX idx_users_email_covering ON users (email)\n  INCLUDE (name, avatar_url);  -- index-only scan for profile lookups\n```\n\n### Index Anti-patterns\n\n```sql\n-- WRONG: Index on low-cardinality column alone\nCREATE INDEX idx_users_active ON users (is_active);  -- boolean = 2 values\n\n-- WRONG: Too many indexes (slows writes)\n-- Every INSERT/UPDATE must update ALL indexes\n\n-- CORRECT: Composite index targeting actual queries\nCREATE INDEX idx_users_active_created ON users (is_active, created_at DESC)\n  WHERE is_active = true;\n```\n\n## Query Optimization\n\n### Reading EXPLAIN Plans\n\n```sql\nEXPLAIN ANALYZE SELECT u.name, COUNT(o.id)\nFROM users u\nJOIN orders o ON o.user_id = u.id\nWHERE u.status = 'active'\nGROUP BY u.name;\n\n-- Key things to look for:\n-- Seq Scan         -> missing index (on large tables)\n-- Nested Loop      -> fine for small sets, bad for large joins\n-- Hash Join         -> good for large equi-joins\n-- Sort             -> consider index to avoid sort\n-- actual time      -> real execution time\n-- rows             -> if estimated vs actual differ wildly, run ANALYZE\n```\n\n### N+1 Query Detection and Prevention\n\n```python\n# WRONG: N+1 queries (1 query for users + N queries for orders)\nusers = db.query(User).all()\nfor user in users:\n    orders = db.query(Order).filter(Order.user_id == user.id).all()  # N queries!\n\n# CORRECT: Eager loading with SQLAlchemy\nusers = db.query(User).options(joinedload(User.orders)).all()\n\n# CORRECT: Batch query\nuser_ids = [u.id for u in users]\norders = db.query(Order).filter(Order.user_id.in_(user_ids)).all()\norders_by_user = defaultdict(list)\nfor order in orders:\n    orders_by_user[order.user_id].append(order)\n```\n\n```javascript\n// WRONG: N+1 with Prisma\nconst users = await prisma.user.findMany();\nfor (const user of users) {\n  const orders = await prisma.order.findMany({ where: { userId: user.id } }); // N+1!\n}\n\n// CORRECT: Include relation\nconst users = await prisma.user.findMany({\n  include: { orders: true },\n});\n\n// CORRECT: Batch with findMany + in\nconst userIds = users.map((u) => u.id);\nconst orders = await prisma.order.findMany({\n  where: { userId: { in: userIds } },\n});\n```\n\n### Pagination\n\n```sql\n-- WRONG: OFFSET pagination (rescans all skipped rows)\nSELECT * FROM posts ORDER BY created_at DESC LIMIT 20 OFFSET 10000;\n\n-- CORRECT: Cursor-based pagination (keyset)\nSELECT * FROM posts\nWHERE created_at < '2024-01-15T10:30:00Z'\nORDER BY created_at DESC\nLIMIT 20;\n```\n\n## Migration Patterns\n\n### Safe Migration Rules\n\n```\n1. Never rename a column in one step (add new, migrate data, drop old)\n2. Never drop a column that's still read by running code\n3. Add columns as nullable or with defaults\n4. Create indexes CONCURRENTLY to avoid locking\n5. Test rollback before deploying\n```\n\n### Zero-Downtime Migration Example\n\n```sql\n-- Step 1: Add new column (safe, no lock)\nALTER TABLE users ADD COLUMN display_name TEXT;\n\n-- Step 2: Backfill data (do in batches)\nUPDATE users SET display_name = name WHERE display_name IS NULL AND id BETWEEN 1 AND 10000;\n\n-- Step 3: Deploy code that writes to BOTH columns\n-- Step 4: Deploy code that reads from new column\n-- Step 5: Drop old column (after confirming no reads)\nALTER TABLE users DROP COLUMN name;\n```\n\n### Index Creation\n\n```sql\n-- WRONG: Blocks writes on the table\nCREATE INDEX idx_orders_user ON orders (user_id);\n\n-- CORRECT: Non-blocking (PostgreSQL)\nCREATE INDEX CONCURRENTLY idx_orders_user ON orders (user_id);\n```\n\n## Connection Pooling\n\n```\nRule of thumb: connections = (CPU cores * 2) + disk spindles\nFor most apps: 10-20 connections per application instance\n```\n\n```python\n# SQLAlchemy connection pool\nengine = create_engine(\n    DATABASE_URL,\n    pool_size=10,          # maintained connections\n    max_overflow=20,       # extra connections under load\n    pool_timeout=30,       # seconds to wait for connection\n    pool_recycle=1800,     # recycle connections every 30 min\n    pool_pre_ping=True,    # verify connection before use\n)\n```\n\n```javascript\n// Prisma datasource\n// In schema.prisma:\n// datasource db {\n//   provider = \"postgresql\"\n//   url      = env(\"DATABASE_URL\")\n// }\n// Connection limit via URL: ?connection_limit=10&pool_timeout=30\n```\n\n## ORM Best Practices\n\n### Select Only What You Need\n\n```python\n# WRONG: Fetches all columns\nusers = db.query(User).all()\n\n# CORRECT: Select specific columns\nusers = db.query(User.id, User.name).all()\n```\n\n```javascript\n// WRONG: Fetches everything\nconst users = await prisma.user.findMany();\n\n// CORRECT: Select specific fields\nconst users = await prisma.user.findMany({\n  select: { id: true, name: true, email: true },\n});\n```\n\n### Bulk Operations\n\n```python\n# WRONG: Individual inserts in a loop\nfor item in items:\n    db.add(Item(**item))\n    db.commit()  # commit per item!\n\n# CORRECT: Bulk insert\ndb.bulk_insert_mappings(Item, items)\ndb.commit()\n```\n\n```javascript\n// WRONG: Sequential creates\nfor (const item of items) {\n  await prisma.item.create({ data: item });\n}\n\n// CORRECT: Batch create\nawait prisma.item.createMany({ data: items });\n\n// CORRECT: Transaction for dependent operations\nawait prisma.$transaction([\n  prisma.user.create({ data: userData }),\n  prisma.profile.create({ data: profileData }),\n]);\n```\n\n## NoSQL Design Patterns\n\n### Document Database (MongoDB)\n\n```javascript\n// Design for access patterns, not normalization\n// Embed when: 1:1, 1:few, data read together\n// Reference when: 1:many, many:many, data grows unbounded\n\n// WRONG: Normalizing in MongoDB like SQL\n// users collection: { _id, name }\n// addresses collection: { _id, userId, street }  // requires joins\n\n// CORRECT: Embed bounded, co-accessed data\n{\n  _id: ObjectId(\"...\"),\n  name: \"Alice\",\n  addresses: [\n    { street: \"123 Main St\", city: \"NYC\", type: \"home\" },\n    { street: \"456 Work Ave\", city: \"NYC\", type: \"work\" }\n  ]\n}\n\n// CORRECT: Reference unbounded or independent data\n// user: { _id, name, orderIds: [ObjectId(\"...\")] }\n// orders: { _id, userId, items: [...], total: 99.99 }\n```\n\n### Key-Value / Redis Patterns\n\n```\n# Cache-aside pattern\n1. Check cache for key\n2. If miss, query database\n3. Store result in cache with TTL\n4. Return result\n\n# Cache invalidation\n- TTL-based: SET key value EX 3600 (1 hour)\n- Event-based: Delete key on write\n- Write-through: Update cache on every write\n```\n\n## Common Anti-Patterns Summary\n\n```\nAVOID                              DO INSTEAD\n-------------------------------------------------------------------\nSELECT *                           SELECT specific columns\nOFFSET pagination                  Cursor-based pagination\nN+1 queries                        Eager load or batch queries\nIndexing every column              Index based on query patterns\nUUID v4 as primary key             UUID v7 or BIGSERIAL (better locality)\nStoring money as FLOAT             Use DECIMAL / BIGINT (cents)\nNo foreign keys \"for speed\"        Use foreign keys (data integrity)\nGiant migrations                   Small, reversible steps\nNo connection pooling              Always pool connections\nPremature denormalization          Normalize first, denormalize with data\n```","tags":["database","design","claude","workflow","cloudai-x","agent-skills","ai-agents","claude-code","codex","cursor","skills"],"capabilities":["skill","source-cloudai-x","skill-database-design","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-codex","topic-cursor","topic-skills","topic-workflow"],"categories":["claude-workflow-v2"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/CloudAI-X/claude-workflow-v2/database-design","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add CloudAI-X/claude-workflow-v2","source_repo":"https://github.com/CloudAI-X/claude-workflow-v2","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 1352 github stars · SKILL.md body (10,386 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-03T00:52:55.607Z","embedding":null,"createdAt":"2026-04-18T21:54:52.553Z","updatedAt":"2026-05-03T00:52:55.607Z","lastSeenAt":"2026-05-03T00:52:55.607Z","tsv":"'+1':27,58,644,652,729,749,1355 '-01':812 '-15':813 '-20':1002 '0':270,301 '00z':816 '1':82,329,346,654,829,882,918,1202,1203,1204,1211,1289,1319 '10':1001,1018,1071 '10000':798,920 '123':1248 '1800':1038 '1nf':135,142 '2':88,528,843,898,995,1294 '20':796,823,1023 '2024':439,444,811 '2nf':141,156 '3':94,855,922,1299 '30':815,1030,1042,1074 '3600':1318 '3nf':91,155,209 '4':99,863,931,1306 '456':1256 '5':106,870,940 '6':113 '7':118 '8':123 '99.99':1279 'accept':285 'access':1196,1240 'across':190 'activ':431,435,522,526,552,557,563,589 'actual':546,629,638 'add':295,837,856,883,892 'address':1228,1246 'alic':1245 'alon':517 'alter':292,889,948 'alway':1407 'analyz':572,642 'anti':127,507,1338 'anti-pattern':126,506,1337 'app':1000 'append':724 'applic':306,1005 'array':390 'asid':1287 'ask':33 'atom':136 'avatar':496 'ave':1258 'avoid':290,482,627,868,1341 'await':734,743,755,772,1107,1115,1162,1169,1178 'b':367,382 'b-tree':366,381 'backfil':899 'bad':611 'base':802,1313,1323,1352,1366 'batch':693,761,903,1167,1360 'begin':316 'best':1076 'better':379,1379 'bigint':1387 'bigseri':1378 'block':958,975 'boolean':527 'bound':1237 'brin':398 'bulk':1124,1145 'cach':1286,1291,1303,1309,1332 'cache-asid':1285 'cardin':515 'cent':1388 'check':268,1290 'checklist':74,129 'citi':1251,1259 'co':1239 'co-access':1238 'code':307,854,924,933 'collect':1225,1229 'column':150,163,172,296,409,448,480,516,833,847,857,885,893,929,938,943,952,1087,1095,1347,1364 'comment':297,311,325,327,342,344 'commit':1141 'common':1336 'composit':406,543 'concurr':866,979 'condit':460 'configur':119 'confirm':945 'connect':120,987,992,1003,1009,1020,1025,1035,1040,1049,1065,1069,1405,1409 'consid':624 'const':732,737,741,753,765,770,1105,1113,1158 'copi':72 'core':994 'correct':206,542,680,692,750,760,799,972,1092,1109,1144,1166,1173,1235,1263 'count':291,298,312,326,328,343,345,575 'counter':288 'cover':451,477,490 'cpu':993 'creat':176,210,226,239,244,308,415,420,424,437,442,461,468,485,518,548,553,558,792,809,819,864,963,977,1012,1156,1168 'creation':955 'critic':110 'current':67 'cursor':801,1351 'cursor-bas':800,1350 'custom':183,186,212,233,237 'data':40,55,404,840,900,1164,1171,1182,1185,1206,1215,1241,1268,1397,1416 'databas':2,5,18,35,42,62,69,78,1014,1063,1191,1298 'database-design':1 'datasourc':1054,1057 'db':1058 'db.add':1137 'db.bulk':1147 'db.commit':1140,1152 'db.query':663,671,686,703,1089,1097 'decim':1386 'default':242,300,369,862 'defaultdict':713 'delet':337,1324 'denorm':96,273,274,286,1411,1414 'depend':145,151,159,166,1176 'deploy':874,923,932 'desc':560,794,821 'design':3,4,21,43,49,70,79,100,131,1188,1194 'detect':646 'differ':639 'disk':996 'display':894,907,911 'document':1190 'downtim':877 'drop':841,845,941,951 'duplic':189 'eager':681,1357 'elsif':334 'email':187,221,489,493,1122 'emb':1200,1236 'end':351,355 'engin':1011,1013 'entiti':84 'env':1062 'equal':370,376 'equi':621 'equi-join':620 'estim':636 'evalu':95 'event':1322 'event-bas':1321 'everi':536,1041,1334,1363 'everyth':1104 'ex':1317 'exampl':879 'execut':632 'explain':568,571 'extra':1024 'faster':475 'fetch':1085,1103 'field':1112 'filter':673,705 'findmani':763 'fine':607 'first':447,1413 'fix':25,59 'float':1384 'foreign':1390,1395 'form':134 'full':153,386,396 'full-text':385,395 'function':309 'geometri':392 'giant':1399 'gin':384 'gist':391 'good':617 'group':140,196,590 'grow':1216 'hash':375,615 'home':1254 'hour':1320 'id':179,213,229,234,238,248,253,257,259,263,331,333,348,350,585,675,696,708,723,916,971,986,1118,1226,1230,1242,1270,1275 'identifi':83 'idx':417,463,487,520,550,965,980 'includ':479,494,751,757 'independ':1267 'index':7,53,101,358,360,407,416,427,452,455,457,462,474,478,486,499,505,511,519,533,541,544,549,601,625,865,954,964,978,1362,1365 'index-on':498 'individu':1128 'insert':320,1129,1146,1148 'insert/update':537 'instanc':1006 'instead':1343 'int':199,205,235,254,260,265,299 'integr':1398 'invalid':1310 'involv':64 'issu':283 'item':247,1134,1136,1138,1139,1143,1150,1151,1159,1161,1165,1172,1277 'javascript':726,1052,1101,1153,1193 'join':580,614,616,622,1234 'joinedload':689 'jsonb':389 'key':149,162,171,182,216,232,251,593,1281,1293,1315,1325,1374,1391,1396 'key-valu':1280 'keyset':804 'languag':356 'larg':399,603,613,619 'leftmost':412 'like':373,1222 'limit':795,822,1066,1070 'list':714 'load':46,682,1027,1358 'local':1380 'lock':869,888 'look':596 'lookup':476,484,504 'loop':606,1132 'low':514 'low-cardin':513 'm':41 'main':1249 'maintain':1019 'mani':532,1212,1213,1214 'map':1149 'match':459 'matter':411 'max':1021 'measur':279 'migrat':12,30,50,115,824,827,839,878,1400 'min':1043 'minimum':92 'miss':600,1296 'model':56 'money':1382 'mongodb':1192,1221 'must':538 'n':26,57,643,651,658,678,728,748,1354 'name':184,193,201,217,495,895,908,909,912,953,1120,1227,1244,1271 'natur':402 'need':97,1082 'nest':605 'never':830,844 'new':838,884,937 'new.post':332 'non':148,161,170,974 'non-block':973 'non-key':147,160,169 'normal':37,89,133,207,1199,1219,1412 'nosql':17,1187 'null':220,225,267,354,914 'nullabl':859 'nyc':1252,1260 'o':582 'o.id':576 'o.user':584 'objectid':1243,1273 'offset':781,797,1348 'old':842,942 'old.post':349 'one':835 'op':319,336 'oper':1125,1177 'optim':10,23,52,109,566 'option':688 'order':178,191,228,246,252,256,403,410,464,467,581,661,670,672,702,704,710,716,718,719,725,742,758,771,790,817,966,969,981,984,1274 'order.user':674,722 'order.user_id.in':706 'orderid':1272 'orm':38,1075 'overflow':1022 'pagin':778,782,803,1349,1353 'partial':144,449,454 'pattern':13,104,128,508,825,1189,1197,1284,1288,1339,1369 'pend':465,472 'per':1004,1142 'perform':36,282 'ping':1046 'pk':154 'plan':29,114,569 'plpgsql':357 'pool':121,988,1010,1016,1028,1036,1044,1072,1406,1408 'post':294,323,340,789,807 'postgresql':976,1060 'practic':1077 'pre':1045 'precomput':287 'prefix':374,413 'prematur':1410 'prevent':648 'primari':181,215,231,250,1373 'principl':132 'prisma':731,1053,1179 'prisma.item.create':1163 'prisma.item.createmany':1170 'prisma.order.findmany':744,773 'prisma.profile.create':1184 'prisma.user.create':1181 'prisma.user.findmany':735,756,1108,1116 'problem':28 'product':258,262 'product1':192,197 'product2':200,203 'profil':503 'profiledata':1186 'progress':77,80 'proof':280 'provid':1059 'python':649,1007,1083,1126 'qti':198,204 'quantiti':264,269 'queri':9,24,51,103,111,547,565,645,653,655,659,679,694,1297,1356,1361,1368 'rang':371,393 'rare':378 'read':567,851,935,947,1207 'real':631 'recycl':1037,1039 'redi':1283 'refer':236,255,261,1209,1264 'relat':752 'relationship':86 'renam':831 'repeat':139,195 'requir':1233 'rescan':783 'result':1301,1308 'return':313,353,1307 'revers':1402 'rollback':872 'row':458,634,786 'rule':414,828,989 'run':641,853 'safe':826,886 'scan':501,599 'schema':6,48,90,130 'schema.prisma':1056 'search':388 'second':1031 'select':573,787,805,1078,1093,1110,1117,1344,1345 'seq':598 'sequenti':1155 'serial':180,214,230,249 'set':324,341,610,906,1314 'size':1017 'skill' 'skill-database-design' 'skip':60,446,785 'slow':534 'small':609,1401 'smaller':473 'sort':372,623,628 'source-cloudai-x' 'specif':1094,1111,1346 'speed':1393 'spindl':997 'sql':15,173,284,408,453,509,570,779,880,956,1223 'sqlalchemi':684,1008 'st':1250 'status':419,423,430,434,471 'step':81,87,93,98,105,112,117,122,836,881,897,921,930,939,1403 'still':850 'store':1300,1381 'strategi':8,54,116,359 'street':1232,1247,1255 'summari':1340 'support':428 't10':814 'tabl':22,177,211,227,245,293,400,483,604,890,949,962 'target':545 'task':68 'test':871 'text':185,188,194,202,218,222,387,397,896 'tg':318,335 'thing':594 'thumb':991 'time':630,633 'timeout':1029,1073 'timestamp':405 'timestamptz':241 'togeth':1208 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-skills' 'topic-workflow' 'total':1278 'track':76 'transact':1174,1180 'transit':158 'tree':368,383 'trigger':47,304,314 'true':564,759,1047,1119,1121,1123 'ttl':1305,1312 'ttl-base':1311 'type':361,394,1253,1261 'u':579,699,768 'u.id':586,697,769 'u.name':574,592 'u.status':588 'unbound':1217,1265 'uniqu':223 'unnorm':175 'updat':302,310,322,339,539,904,1331 'url':497,1015,1061,1064,1068 'use':19,365,1051,1385,1394 'user':418,422,488,492,521,524,551,555,578,657,662,664,667,669,685,687,695,701,707,712,721,733,738,740,754,891,905,950,967,970,982,985,1088,1090,1096,1106,1114,1224,1269 'user.id':676,747,1098 'user.name':1099 'user.orders':690 'userdata':1183 'userid':746,766,775,777,1231,1276 'users.map':767 'uuid':1370,1375 'v4':1371 'v7':1376 'valid':124 'valu':137,529,1282,1316 'verifi':1048 'via':303,1067 'vs':637 'wait':1033 'wild':640 'work':63,1257,1262 'workflow':71 'write':107,535,926,959,1327,1329,1335 'write-through':1328 'wrong':174,510,530,650,727,780,957,1084,1102,1127,1154,1218 'yes':432,440 'zero':876 'zero-downtim':875","prices":[{"id":"36f48c83-4fd8-40c3-a339-2938e486c87f","listingId":"0a029f02-023f-42d8-b29e-0b998c0f09c9","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"CloudAI-X","category":"claude-workflow-v2","install_from":"skills.sh"},"createdAt":"2026-04-18T21:54:52.553Z"}],"sources":[{"listingId":"0a029f02-023f-42d8-b29e-0b998c0f09c9","source":"github","sourceId":"CloudAI-X/claude-workflow-v2/database-design","sourceUrl":"https://github.com/CloudAI-X/claude-workflow-v2/tree/main/skills/database-design","isPrimary":false,"firstSeenAt":"2026-04-18T21:54:52.553Z","lastSeenAt":"2026-05-03T00:52:55.607Z"}],"details":{"listingId":"0a029f02-023f-42d8-b29e-0b998c0f09c9","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"CloudAI-X","slug":"database-design","github":{"repo":"CloudAI-X/claude-workflow-v2","stars":1352,"topics":["agent-skills","ai","ai-agents","claude-code","codex","cursor","skills","workflow"],"license":"mit","html_url":"https://github.com/CloudAI-X/claude-workflow-v2","pushed_at":"2026-02-14T18:09:29Z","description":"Universal Claude Code workflow plugin with agents, skills, hooks, and commands","skill_md_sha":"7b18c69cb993c942ea781db8b3437ebeb25ccfe9","skill_md_path":"skills/database-design/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/CloudAI-X/claude-workflow-v2/tree/main/skills/database-design"},"layout":"multi","source":"github","category":"claude-workflow-v2","frontmatter":{"name":"database-design","description":"Designs database schemas, indexing strategies, query optimization, and migration patterns for SQL and NoSQL databases. Use when designing tables, optimizing queries, fixing N+1 problems, planning migrations, or when asked about database performance, normalization, ORMs, or data modeling."},"skills_sh_url":"https://skills.sh/CloudAI-X/claude-workflow-v2/database-design"},"updatedAt":"2026-05-03T00:52:55.607Z"}}