Skip to content
d3 Wiki
09.02

Schema design standards and naming

Schemas that are obvious to read and cheap to change.

Updated
Oct 3, 2026
On this page

Purpose

Schemas that are obvious to read and cheap to change.

The standard

  • snake_case; plural table names (panels), singular column names; primary key id uuid default gen_random_uuid().

  • Every table has created_at timestamptz default now(); mutable tables add updated_at (trigger-maintained) and updated_by.

  • Foreign keys always declared, named <table>_id, with explicit on delete behavior.

  • Units in column names (width_mm, weight_kg, angle_deg); store SI, convert at the edge.

  • Enums as Postgres enum types or text + check constraint; prefer check when values will change.

  • jsonb for document-shaped data (editor content, tool settings); never for data you'll filter or join on.

  • Indexes on every FK and every column used in where/order by; no premature composite indexes.

  • Soft delete (deleted_at) only where restore is a real requirement; otherwise hard delete with on delete cascade thought through.

  • Comment every table (comment on table … is '…') — it shows up in the dashboard and in generated types.

Anti-patterns

Storing arrays of ids instead of join tables; varchar(255) by habit (use text); nullable everything.

Owner: Matt · Last reviewed: 2026-09