Skip to content

Mixins

File location: schema/mixins/<name>.yaml

mixin: timestamps
columns:
- name: created_at
type: timestamptz
nullable: false
default: now()
- name: updated_at
type: timestamptz
nullable: false
default: now()
indexes:
- columns: [created_at]
triggers:
- name: set_{table}_updated_at
timing: BEFORE
events: [UPDATE]
function: update_timestamp
for_each: ROW
checks:
- name: chk_{table}_dates
expression: 'updated_at >= created_at'
rls: true
force_rls: true
policies:
- name: '{table}_owner_policy'
for: ALL
to: app_user
using: 'owner_id = current_user_id()'
grants:
- to: app_readonly
privileges: [SELECT]

Tables reference mixins by name:

table: orders
mixins:
- timestamps
columns:
- name: id
type: uuid
primary_key: true
# timestamps columns, indexes, triggers, checks, policies, grants merged automatically
PropertyDescription
columnsAdded before table’s own columns
indexesMerged into table indexes
checksMerged into table checks
triggersMerged into table triggers
policiesMerged into table policies
grantsMerged into table grants
rlsEnables RLS on consuming table
force_rlsForces RLS on consuming table

The {table} placeholder in any mixin string value is replaced with the consuming table’s name. This ensures unique constraint/trigger/policy names across tables.

# In the mixin:
triggers:
- name: set_{table}_updated_at
# Applied to table "orders", becomes:
triggers:
- name: set_orders_updated_at
  • Columns: Mixin columns come first. If a table defines a column with the same name as a mixin column, the table’s definition wins.
  • Multiple mixins: Applied in order. Later mixins can override earlier ones.
  • All other properties: Concatenated (indexes, checks, triggers, policies, grants).