

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# SQL & Database Operations — Cursor Rules2# Comprehensive rules for database design, querying, and operations34## Project Context5You are working on a project that uses a relational database (PostgreSQL, MySQL, or6SQLite). The codebase interacts with the database through an ORM (Prisma, SQLAlchemy,7Drizzle) or raw SQL. Queries must be efficient, safe from injection, and the schema8must be well-designed for the application's access patterns.910## Tech Stack11- PostgreSQL (preferred) / MySQL / SQLite12- ORM: Prisma, SQLAlchemy, Drizzle, or TypeORM13- Migrations: Prisma Migrate, Alembic, or raw SQL migrations14- Connection pooling: PgBouncer or built-in pool15- Query monitoring: EXPLAIN ANALYZE, pg_stat_statements1617## Schema Design1819### Naming Conventions20- Tables: plural snake_case (e.g., `users`, `order_items`, `product_categories`)21- Columns: snake_case (e.g., `created_at`, `user_id`, `is_active`)22- Primary keys: `id` (auto-incrementing integer or UUID)23- Foreign keys: `{referenced_table_singular}_id` (e.g., `user_id`, `order_id`)24- Indexes: `idx_{table}_{columns}` (e.g., `idx_users_email`, `idx_orders_user_id_status`)25- Unique constraints: `uq_{table}_{columns}` (e.g., `uq_users_email`)26- Boolean columns: `is_` or `has_` prefix (e.g., `is_active`, `has_verified_email`)27- Timestamps: `created_at`, `updated_at`, `deleted_at` (for soft deletes)28- Enums: singular noun (e.g., `order_status`, `payment_method`)2930### Table Design Rules31```sql32CREATE TABLE users (33 id BIGSERIAL PRIMARY KEY,34 email VARCHAR(255) NOT NULL,35 name VARCHAR(100) NOT NULL,36 password_hash VARCHAR(255) NOT NULL,37 role VARCHAR(20) NOT NULL DEFAULT 'user',38 is_active BOOLEAN NOT NULL DEFAULT true,39 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),40 updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),4142 CONSTRAINT uq_users_email UNIQUE (email),43 CONSTRAINT chk_users_role CHECK (role IN ('user', 'admin', 'moderator'))44);4546CREATE TABLE orders (47 id BIGSERIAL PRIMARY KEY,48 user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,49 status VARCHAR(20) NOT NULL DEFAULT 'pending',50 total NUMERIC(10, 2) NOT NULL DEFAULT 0,51 notes TEXT,52 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),53 updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),5455 CONSTRAINT chk_orders_status CHECK (status IN ('pending', 'confirmed', 'shipped', 'delivered', 'cancelled')),56 CONSTRAINT chk_orders_total CHECK (total >= 0)57);5859CREATE INDEX idx_orders_user_id ON orders(user_id);60CREATE INDEX idx_orders_status ON orders(status);61CREATE INDEX idx_orders_created_at ON orders(created_at DESC);62```6364### Design Principles65- Every table must have a primary key66- Use appropriate data types — don't store numbers as strings67- Use `TIMESTAMPTZ` (not `TIMESTAMP`) for time-aware timestamps68- Use `NUMERIC`/`DECIMAL` for money, never `FLOAT` or `DOUBLE`69- Add `NOT NULL` constraints unless the column genuinely needs nulls70- Use `CHECK` constraints for valid value ranges71- Add foreign key constraints for referential integrity72- Include `created_at` and `updated_at` on every table73- Normalize to 3NF, denormalize selectively for read performance7475## Indexing Strategy7677### When to Index78- Foreign key columns (always)79- Columns used in `WHERE` clauses frequently80- Columns used in `ORDER BY` clauses81- Columns used in `JOIN` conditions82- Columns used in `UNIQUE` constraints (automatically indexed)8384### Index Types85```sql86-- B-tree (default, good for equality and range queries)87CREATE INDEX idx_orders_created_at ON orders(created_at DESC);8889-- Composite index (for multi-column queries — column order matters)90CREATE INDEX idx_orders_user_status ON orders(user_id, status);9192-- Partial index (for filtered subsets — smaller and faster)93CREATE INDEX idx_orders_pending ON orders(created_at) WHERE status = 'pending';9495-- GIN index (for full-text search, JSONB, arrays)96CREATE INDEX idx_products_tags ON products USING GIN(tags);9798-- Expression index (for computed lookups)99CREATE INDEX idx_users_email_lower ON users(LOWER(email));100```101102### Indexing Rules103- Index foreign keys to prevent slow DELETE cascades104- Put the most selective column first in composite indexes105- Use partial indexes for queries that always filter the same way106- Don't over-index — each index slows down writes107- Monitor unused indexes with `pg_stat_user_indexes`108109## Query Patterns110111### Efficient Queries112```sql113-- Pagination: cursor-based (fast on large tables)114SELECT * FROM orders115WHERE user_id = $1 AND id < $2116ORDER BY id DESC117LIMIT 20;118119-- Pagination: offset-based (simple but slow on large offsets)120SELECT * FROM orders WHERE user_id = $1121ORDER BY created_at DESC122LIMIT 20 OFFSET 40;123124-- Aggregation with filtering125SELECT126 DATE_TRUNC('month', created_at) AS month,127 COUNT(*) AS order_count,128 SUM(total) AS revenue129FROM orders130WHERE status = 'delivered' AND created_at >= NOW() - INTERVAL '12 months'131GROUP BY DATE_TRUNC('month', created_at)132ORDER BY month DESC;133134-- Avoid SELECT * in production queries135SELECT id, email, name, role FROM users WHERE id = $1;136137-- Use EXISTS instead of COUNT for existence checks138SELECT EXISTS(SELECT 1 FROM users WHERE email = $1) AS email_taken;139```140141### Joins142```sql143-- Prefer explicit JOIN syntax over WHERE clause joins144SELECT o.id, o.total, u.name, u.email145FROM orders o146INNER JOIN users u ON u.id = o.user_id147WHERE o.status = 'pending'148ORDER BY o.created_at DESC;149150-- Use LEFT JOIN only when you need rows without matches151SELECT u.id, u.name, COUNT(o.id) AS order_count152FROM users u153LEFT JOIN orders o ON o.user_id = u.id154GROUP BY u.id, u.name;155```156157## Migrations158159### Rules160- Every schema change goes through a migration — never modify production manually161- Migrations must be reversible (include both `up` and `down`)162- Use descriptive migration names: `add_status_to_orders`, `create_product_categories`163- Never modify an existing migration that has been applied in production164- Test migrations against a copy of production data when possible165- Add indexes concurrently in production: `CREATE INDEX CONCURRENTLY`166167### Safe Migration Patterns168```sql169-- Adding a column (safe — no lock on reads)170ALTER TABLE users ADD COLUMN phone VARCHAR(20);171172-- Adding NOT NULL column (safe approach — add nullable, backfill, then constrain)173ALTER TABLE users ADD COLUMN bio TEXT;174UPDATE users SET bio = '' WHERE bio IS NULL;175ALTER TABLE users ALTER COLUMN bio SET NOT NULL;176177-- Adding index without locking writes178CREATE INDEX CONCURRENTLY idx_users_phone ON users(phone);179```180181## Security182- ALWAYS use parameterized queries — never concatenate user input into SQL183- Use the ORM's query builder or prepared statements184- Grant minimum database permissions to the application role185- Never expose database errors directly to the API response186- Sanitize and validate all user input before querying187- Use row-level security (RLS) in PostgreSQL for multi-tenant applications188189## Performance190191### Query Optimization192- Use `EXPLAIN ANALYZE` to understand query execution plans193- Look for sequential scans on large tables — add indexes194- Avoid `SELECT *` — fetch only needed columns195- Use `LIMIT` on all queries that return lists196- Use `EXISTS` instead of `COUNT(*)` for boolean checks197- Batch inserts with `INSERT INTO ... VALUES (...), (...), (...)`198- Use `ON CONFLICT` (upsert) instead of select-then-insert199200### Connection Management201- Use connection pooling (PgBouncer or ORM built-in pool)202- Set appropriate pool size (typically 2x CPU cores)203- Close connections in error handlers204- Use read replicas for read-heavy workloads205206## Common Pitfalls207- N+1 queries: fetching related records in a loop instead of a JOIN or IN clause208- Missing indexes on foreign keys (slow cascading deletes)209- Using OFFSET pagination on large tables (scans all skipped rows)210- Storing monetary values as float (precision errors)211- Not using transactions for multi-step operations212- Forgetting to add indexes on columns used in WHERE/ORDER BY213- Locking entire tables with ALTER TABLE on production (use CONCURRENTLY)214- Not setting statement timeouts (one slow query blocks the pool)215- Trusting ORM-generated queries without checking EXPLAIN output216
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/tailwindcss/.cursorrules · 16 | .cursorrules | lint-formatstylearchui+3 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/clean-code/.cursorrules · 16 | .cursorrules | styledo-notagent-behaviourdocs | 57/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-14-app-router/.cursorrules · 16 | .cursorrules | teststyletypestesting-strategy+3 | 71/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-app-router/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-typescript/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/survivorforge-cursor-rules-rules-database-sql-cursorrules)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.
Directory