Wode DB Schema Pattern
You are strictly required to follow this PostgreSQL schema design pattern. When creating or modifying table structures, you MUST adhere to every rule below.
1. Core Rules (MUST FOLLOW)
Table Naming
- MUST use PostgreSQL schema for isolation, NEVER use table name prefixes
- MUST prefer singular form:
user, order
- System tables MAY use plural:
users, groups
Data Types
- MUST use:
text, bigint, jsonb, bool, timestamptz
- MUST use
text[] for tag-like arrays
- NEVER use
varchar(n) — validate at business layer + check constraints
ID Strategy
- MUST use K-Sortable random primary keys (ULID or UUIDv7)
- MUST add type prefix for readability:
user_, order_
- NEVER use auto-increment IDs
Field Naming
- Timestamps: MUST use
_at suffix (created_at, updated_at, deleted_at)
- Foreign keys: MUST use
_id suffix (user_id, customer_id)
- Discriminators: MUST use
_type suffix (owner_type, entity_type)
- Enum values: MUST use PascalCase (
Active, Draft, User)
2. Standard Field Template
create table example (
-- Identifiers
id text not null default 'prefix_' || uuidv7(),
tid bigint not null default current_tenant_id(),
uid uuid not null default gen_random_uuid(),
sid bigint not null default (next_entity_sid('Type')),
-- Timestamps
created_at timestamptz not null default current_timestamp,
updated_at timestamptz not null default current_timestamp,
deleted_at timestamptz,
-- State Machine
state text, -- Active, Inactive, Suspended
status text, -- Draft, Pending, Approved
-- Extension Data
attributes jsonb not null default '{}', -- Client read/write
properties jsonb not null default '{}', -- Server managed, client read-only
extensions jsonb not null default '{}', -- Internal use, hidden from client
metadata jsonb not null default '{}',
-- Polymorphic Association
owner_id text,
owner_type text, -- User, Team, Department
-- Constraints
primary key (tid, id),
unique (tid, uid)
);
3. Extension Data Strategy
When adding flexible data fields, you MUST follow this separation:
| Field |
Access |
Purpose |
attributes |
Client read/write |
User-defined custom fields |
properties |
Server write, client read |
Server-managed configuration |
extensions |
Internal only |
Hidden from client API |
metadata |
Supplementary |
Descriptive content |
4. Multi-Tenant Isolation
- Every business table MUST include
tid bigint not null default current_tenant_id()
- Primary key MUST be composite:
primary key (tid, id)
- Unique constraints MUST include
tid: unique (tid, uid)
5. Detailed Reference
For complete field catalog (external IDs, audit trail, ownership pattern, generated columns, index naming, schema organization), read: references/db-schema-design.md
1---2name: wode-db-schema-pattern3description: Use when designing, creating, or modifying PostgreSQL table schemas in the Wode project, including ID strategy, multi-tenant isolation, or naming conventions4---56# Wode DB Schema Pattern78You are strictly required to follow this PostgreSQL schema design pattern. When creating or modifying table structures, you MUST adhere to every rule below.910## 1. Core Rules (MUST FOLLOW)1112### Table Naming13- MUST use PostgreSQL schema for isolation, NEVER use table name prefixes14- MUST prefer singular form: `user`, `order`15- System tables MAY use plural: `users`, `groups`1617### Data Types18- MUST use: `text`, `bigint`, `jsonb`, `bool`, `timestamptz`19- MUST use `text[]` for tag-like arrays20- NEVER use `varchar(n)` — validate at business layer + check constraints2122### ID Strategy23- MUST use K-Sortable random primary keys (ULID or UUIDv7)24- MUST add type prefix for readability: `user_`, `order_`25- NEVER use auto-increment IDs2627### Field Naming28- Timestamps: MUST use `_at` suffix (`created_at`, `updated_at`, `deleted_at`)29- Foreign keys: MUST use `_id` suffix (`user_id`, `customer_id`)30- Discriminators: MUST use `_type` suffix (`owner_type`, `entity_type`)31- Enum values: MUST use PascalCase (`Active`, `Draft`, `User`)3233## 2. Standard Field Template3435```sql36create table example (37 -- Identifiers38 id text not null default 'prefix_' || uuidv7(),39 tid bigint not null default current_tenant_id(),40 uid uuid not null default gen_random_uuid(),41 sid bigint not null default (next_entity_sid('Type')),4243 -- Timestamps44 created_at timestamptz not null default current_timestamp,45 updated_at timestamptz not null default current_timestamp,46 deleted_at timestamptz,4748 -- State Machine49 state text, -- Active, Inactive, Suspended50 status text, -- Draft, Pending, Approved5152 -- Extension Data53 attributes jsonb not null default '{}', -- Client read/write54 properties jsonb not null default '{}', -- Server managed, client read-only55 extensions jsonb not null default '{}', -- Internal use, hidden from client56 metadata jsonb not null default '{}',5758 -- Polymorphic Association59 owner_id text,60 owner_type text, -- User, Team, Department6162 -- Constraints63 primary key (tid, id),64 unique (tid, uid)65);66```6768## 3. Extension Data Strategy6970When adding flexible data fields, you MUST follow this separation:7172| Field | Access | Purpose |73|-------|--------|---------|74| `attributes` | Client read/write | User-defined custom fields |75| `properties` | Server write, client read | Server-managed configuration |76| `extensions` | Internal only | Hidden from client API |77| `metadata` | Supplementary | Descriptive content |7879## 4. Multi-Tenant Isolation8081- Every business table MUST include `tid bigint not null default current_tenant_id()`82- Primary key MUST be composite: `primary key (tid, id)`83- Unique constraints MUST include `tid`: `unique (tid, uid)`8485## 5. Detailed Reference8687For complete field catalog (external IDs, audit trail, ownership pattern, generated columns, index naming, schema organization), read: [references/db-schema-design.md](references/db-schema-design.md)