Migrations¶
The framework provides per-app SQL migrations tracked in a shared _migrations table.
How It Works¶
- Each app embeds its SQL files with
//go:embed migrations - At startup, the framework calls
RunAppMigrationsfor every app that implementsMigratable - Migrations are applied in filename order, skipping already-applied ones
- Each migration is namespaced by app name in the
_migrationstracking table
Creating Migrations¶
1. Create the SQL File¶
Place migration files in a migrations/ directory inside your app package:
2. Naming Convention¶
Files must end with .up.sql. Use a numeric prefix for ordering:
The framework sorts filenames lexicographically and applies them in order.
3. Embed the Directory¶
4. Implement Migratable¶
Important
Use fs.Sub() to strip the migrations/ prefix. The framework expects the FS root to contain .up.sql files directly.
Example Migration¶
-- 001_create_notes.up.sql
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at DATETIME
);
CREATE INDEX IF NOT EXISTS idx_notes_user_id ON notes (user_id);
Tracking Table¶
The _migrations table is created automatically:
CREATE TABLE IF NOT EXISTS _migrations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
app TEXT NOT NULL,
name TEXT NOT NULL,
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(app, name)
);
Each record stores the app name and migration filename. This namespacing means two apps can both have 001_initial.up.sql without conflict.
Migration Order¶
Migrations run in app registration order (the order you pass apps to NewServer), then by filename within each app. All migrations run before any app's Register() method is called.
Tips¶
- Use
CREATE TABLE IF NOT EXISTSandCREATE INDEX IF NOT EXISTSfor idempotent migrations - Keep migrations small and focused — one table or one alteration per file
- Never modify an already-applied migration — create a new one instead
- The framework does not support down migrations — roll forward with new migrations