postgresql-table-design
Has your agent design and review the structure of tables in PostgreSQL databases. It ensures the design is efficient, secure, and follows best practices to optimize performance.
What it does
This agent helps design and review table structures for PostgreSQL databases. It suggests best practices for data types, indexes, and rules to ensure your database performs well.
When to use it
- ✓When creating a new database.
- ✓When choosing the right data types for your columns.
- ✓When deciding how to organize your data for best performance.
Example of what to ask your AI
“How should I create a table to store customer information, ensuring emails are unique?”
Want more? Open the sections below.
How to use
The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.
Skill link
Ready-to-paste message
How it works
It analyzes your needs and suggests the best column options, indexes, and PostgreSQL-specific rules, considering performance and best practices.
Installation
Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.
In the terminal (Claude Code, Codex, Cursor), in your project folder:
npx skills add wshobson/agents --skill postgresql-table-designOr download just the file:
curl -L https://raw.githubusercontent.com/wshobson/agents/main/plugins/database-design/skills/postgresql-table-design/SKILL.md -o SKILL.mdTechnical content (original SKILL.md)
Original text by the author, straight from GitHub.
PostgreSQL Table Design
When to Use
- Designing a new PostgreSQL schema, or reviewing one before it ships.
- Choosing column types, keys, constraints, or indexes for PostgreSQL specifically.
- Deciding whether and how to partition a large table, or how to store semi-structured data.
- Planning a schema change on a live database without downtime.
The rules and decision points for a PostgreSQL schema. The full data-type catalog, workload
patterns (update-heavy, insert-heavy, upsert, schema evolution), extensions, JSONB indexing,
and worked DDL examples are in references/details.md; open it when a section below points there.
Core Rules
- Define a PRIMARY KEY for reference tables (users, orders, etc.). Not always needed for time-series/event/log data. When used, prefer
BIGINT GENERATED ALWAYS AS IDENTITY; useUUIDonly when global uniqueness/opacity is needed. - Normalize first (to 3NF) to eliminate data redundancy and update anomalies; denormalize only for measured, high-ROI reads where join performance is proven problematic.
- Add NOT NULL everywhere it is semantically required; use DEFAULTs for common values.
- Create indexes for access paths you actually query: PK/unique (auto), FK columns (manual!), frequent filters/sorts, and join keys.
- Prefer TIMESTAMPTZ for event time; NUMERIC for money; TEXT for strings; BIGINT for integers; DOUBLE PRECISION for floats (or
NUMERICfor exact decimal arithmetic).
PostgreSQL Gotchas
- Identifiers: unquoted → lowercased. Avoid quoted/mixed-case names; use
snake_case. - Unique + NULLs: UNIQUE allows multiple NULLs. Use
UNIQUE NULLS NOT DISTINCT (...)(PG15+) to restrict to one NULL. - FK indexes: PostgreSQL does not auto-index FK columns. Add them.
- No silent coercions: length/precision overflows error out (no truncation). Inserting 999 into
NUMERIC(2,0)fails, unlike databases that silently truncate or round. - Sequences/identity have gaps (normal; don't "fix"). Rollbacks, crashes, and concurrent transactions leave gaps (1, 2, 5, 6...).
- Heap storage: no clustered PK by default;
CLUSTERis a one-off reorganization, not maintained on later inserts. - MVCC: updates/deletes leave dead tuples; vacuum handles them—design to avoid hot wide-row churn.
Data Types
- IDs:
BIGINT GENERATED ALWAYS AS IDENTITY;UUIDfor distributed or opaque IDs, generated withuuidv7()(PG18+) orgen_random_uuid(). - Numbers:
BIGINTunless storage is critical;DOUBLE PRECISIONoverREAL;NUMERIC(p,s)for money and exact decimals. - Strings:
TEXT, withCHECK (LENGTH(col) <= n)when a limit is needed;BYTEAfor binary. Case-insensitive lookups: expression index onLOWER(col), orCITEXTwhen a constraint must be case-insensitive. - Time:
TIMESTAMPTZ,DATE,INTERVAL.now()is transaction start;clock_timestamp()is wall clock. - Booleans:
BOOLEAN NOT NULLunless tri-state is required. - Enums:
CREATE TYPE ... AS ENUMonly for small, stable sets; evolving business values getTEXT+CHECKor a lookup table. - JSONB over JSON, indexed with GIN, for optional/semi-structured attributes only.
- Arrays, ranges, network, geometric, full-text, domain, composite, and vector types, plus TOAST storage and collation control: see
references/details.md.
Types to avoid
| Avoid | Use instead |
|---|---|
timestamp (without time zone) |
timestamptz |
char(n), varchar(n) |
text (+ CHECK on length if needed) |
money |
numeric |
timetz |
timestamptz |
timestamptz(0) or any precision |
timestamptz |
serial |
generated always as identity |
Constraints
- PK: implicit UNIQUE + NOT NULL; creates a B-tree index.
- FK: specify
ON DELETE/UPDATE(CASCADE,RESTRICT,SET NULL,SET DEFAULT). Index the referencing column. UseDEFERRABLE INITIALLY DEFERREDfor circular dependencies checked at commit. - UNIQUE: creates a B-tree index; allows multiple NULLs unless
NULLS NOT DISTINCT(PG15+). PreferNULLS NOT DISTINCTunless duplicate NULLs are wanted. - CHECK: row-local; NULL passes (three-valued logic). Combine with
NOT NULL:price NUMERIC NOT NULL CHECK (price > 0). - EXCLUDE: prevents overlaps with operators, e.g.
EXCLUDE USING gist (room_id WITH =, booking_period WITH &&)stops double-booking. Needs a GiST-capable type.
Indexing
…
FAQ
Why shouldn't I use 'varchar(n)'?
'Text' is generally preferred in PostgreSQL as it has no size limits and similar performance. You can add a CHECK constraint if you need to limit the length.
Does PostgreSQL automatically create indexes for foreign keys?
No, PostgreSQL does not automatically create indexes for foreign key columns. You need to add them manually for good query performance.
What are PostgreSQL 'gotchas'?
'Gotchas' are quirks or unexpected behaviors in PostgreSQL that can cause issues if you're not aware of them, such as how identifiers are handled or the lack of automatic indexing on foreign keys.
Details
Original description by the author
Use this skill when designing or reviewing a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features
repo: wshobson/agents
Popularity
- GitHub stars
- 41k
- Ranking position
- #4840
- License
- MIT
- Updated
- 10/15/2026
Comments
- …
More skills from this repository
screen-reader-testing
Has your agent test websites using screen readers to ensure they are accessible.
wshobson/agents
wcag-audit-patterns
Helps your agent audit websites for accessibility and fix issues according to WCAG guidelines.
wshobson/agents
multi-reviewer-patterns
Enables your agent to coordinate parallel code reviews, deduplicating findings and consolidating reports.
wshobson/agents
parallel-debugging
Allows the agent to debug complex issues with parallel investigations and root cause analysis.
wshobson/agents
Similar skills
clickhouse-io
Helps your agent optimize queries and schemas in ClickHouse databases. It applies best practices for high-performance analytical workloads. Use when analytical queries are too slow.
affaan-m/ECC
scientific-db-pubmed-database
Helps your agent search for scientific articles in the biomedical field. It's useful for research needing specific medical information.
affaan-m/ECC
scientific-db-uspto-database
Allows the agent to look up official US patent and trademark data. It's useful for intellectual property research.
affaan-m/ECC