Skip to content

Build from DDL

The Build medium creates a complete database by concatenating and executing all your DDL files in order. No migration history to replay, no ORM to bootstrap — just SQL files executed once.

Terminal window
confiture build --env local
✓ Schema built successfully in 0.4s
→ Created 3 tables, 3 views, 2 functions

Confiture reads your SQL files from numbered directories and executes them in alphabetical order:

db/schema/
├── 00_extensions/
│ └── extensions.sql
├── 01_write/
│ ├── tb_user.sql
│ ├── tb_post.sql
│ └── tb_comment.sql
├── 02_read/
│ ├── v_user.sql
│ ├── v_comment.sql
│ └── v_post.sql
└── 03_functions/
├── fn_create_user.sql
└── fn_create_post.sql

Tables before views. Views before functions. The directory numbering controls the order.

Traditional ORMs create databases by replaying every migration in sequence — 001_initial.sql, 002_add_column.sql, … 087_fix_index.sql. For a project with 87 migrations, that means executing 87 files to create what could be expressed in 5.

Build takes the opposite approach: your current DDL files are the source of truth. One execution, one database, under 1 second.

ApproachFresh DB TimeFiles ExecutedSource of Truth
Migration replay2-30 secondsAll migrations (cumulative)Migration history
Confiture BuildUnder 1 secondCurrent DDL files onlyDDL files
Terminal window
# Build for a specific environment
confiture build --env local
confiture build --env test
confiture build --env ci
# Dry run — show what would be executed
confiture build --env local --dry-run
# Rebuild only views (preserves table data)
confiture build --env local --views-only

During development, you often modify views without changing tables. Instead of dropping and recreating the entire database:

Terminal window
# Only recreate views — table data is preserved
confiture build --env local --views-only

This drops and recreates all v_* views and tv_* materialized tables, leaving tb_* tables (and their data) intact.

Confiture processes directories alphabetically. The numbering convention ensures correct execution order:

DirectoryContentsWhy This Order
00_extensions/CREATE EXTENSION statementsExtensions must exist before tables use them
01_write/CREATE TABLE statements (tb_*)Tables must exist before views reference them
02_read/CREATE VIEW statements (v_*)Views depend on tables
03_functions/CREATE FUNCTION statements (fn_*)Functions may reference tables and views
04_indexes/CREATE INDEX statementsIndexes reference tables
05_seeds/INSERT statementsSeed data requires tables to exist

Within each directory, files are also processed alphabetically. If v_post depends on v_user, name them accordingly (e.g., 01_v_user.sql, 02_v_post.sql) or rely on CREATE OR REPLACE with proper ordering.

The typical development loop:

Terminal window
# Edit a SQL view
vim db/schema/02_read/v_user.sql
# Rebuild views only (fast, preserves data)
confiture build --env local --views-only
# Recompile the GraphQL mapping
fraiseql compile
# Serve
fraiseql run