postgresql-table-design

Design PostgreSQL table schemas with normalization, data types, and constraints.

4|Updated Dec 13, 2025
One-click install
npx skills add https://github.com/linehaul-ai/linehaulai-claude-marketplace --skill postgresql-table-design-linehaul-ai
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: postgresql-table-design
Source: https://github.com/linehaul-ai/linehaulai-claude-marketplace/tree/main/.claude-plugin/supabase/skills/postgres
Command: npx skills add https://github.com/linehaul-ai/linehaulai-claude-marketplace --skill postgresql-table-design-linehaul-ai

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Establishes best practices for PostgreSQL table design, including normalization, data types, indexing, and constraints to ensure scalable, maintainable schemas.

Core Features & Use Cases

  • Primary Keys & IDs: guidance on UUIDs vs BIGINT and when to use each.
  • Normalization vs Denormalization: guidance on balancing data integrity and performance.
  • Data Types & Indexing: recommended types and indexing strategies.
  • Constraints & Auditing: NOT NULL, UNIQUE, CHECK, and audit columns.
  • Real-world patterns and considerations for modeling core tables (e.g., loads, orders, users).

Quick Start

Use these guidelines to design a new table in your schema, including an id UUID with default gen_random_uuid(), created_at TIMESTAMPTZ, and updated_at fields.

Frequently Asked Questions about postgresql-table-design

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I design a PostgreSQL table schema that follows best practices?

PostgreSQL table design applies normalization, appropriate data types, and robust constraints to enforce data integrity. Start with a UUID primary key using gen_random_uuid(), add TIMESTAMPTZ columns for created_at and updated_at, select precise types like NUMERIC for decimals and BIGINT for large integers, and define NOT NULL, UNIQUE, and foreign key constraints to prevent invalid data.

What's the difference between using UUIDs and BIGINT for primary keys in Postgres?

UUID primary keys provide global uniqueness without coordination and work well for distributed systems, while BIGINT offers smaller storage and faster comparisons for centralized databases. Choose UUID for microservices and systems requiring collision-free IDs across nodes; use BIGINT when storage and query performance are critical and IDs are generated sequentially.

How do I normalize a PostgreSQL schema while maintaining performance?

Normalization reduces redundancy by organizing data into separate tables with foreign keys, improving maintainability and consistency. Balance this against denormalization for read-heavy workloads by strategically caching frequently joined columns, but only after profiling; start normalized and denormalize only where analysis shows performance gains justify the trade-off.

What data types should I use for different columns in PostgreSQL?

PostgreSQL schema design recommends TIMESTAMPTZ for timestamps to handle timezones correctly, NUMERIC for precise financial values, TEXT for variable-length strings, BIGINT for large integers, and DOUBLE PRECISION for floating-point math. Avoid generic types; precise type selection improves storage efficiency, query performance, and prevents silent precision loss.

How do I index foreign keys and improve query performance in Postgres?

Index foreign key columns to accelerate joins and prevent sequential scans on lookups. Create indexes on FK columns that are frequently used in WHERE clauses or JOIN conditions; consider MVCC behavior when indexing to ensure visibility tuples don't bloat your indexes, and profile to confirm the index reduces query time before deploying.

What constraints should I add to enforce data integrity in PostgreSQL tables?

Use NOT NULL to prevent missing critical data, UNIQUE for fields that must be distinct, CHECK constraints to validate business rules, and PRIMARY KEY and FOREIGN KEY constraints to enforce relationships. These constraints prevent invalid states at the database level, reducing application logic and ensuring consistency across all queries.