Migration Types π¶
Jetbase supports three flexible types of migrations to fit a variety of database needs: Versioned, Runs Always, and Runs on Change.
FOR ALMOST ALL USE CASES, VERSIONED MIGRATIONS ARE ALL YOUβLL EVER NEED.
- Versioned migrations β the standard and most common type, referenced throughout the docs. These are what youβll use for almost every change to your database.
- Runs Always migrations β designed for cases where you want a migration to run every time you upgrade, perfect for things like refreshing views or permissions.
- Runs On Change migrations β ideal when you want a migration to run only if its contents have been modified, great for managing stored procedures or functions.
Overview¶
| Type | Prefix | Runs When | Notes |
|---|---|---|---|
| Versioned | V |
Once, in order | Perfect for most use cases |
| Runs Always | RA__ |
Every upgrade | |
| Runs On Change | ROC__ |
When file changes |
Versioned Migrations (V)¶
The most common type. These run once, in sequential order, and are tracked by version number.
Filename Format¶
Examples¶
When to Use¶
- Creating or altering tables
- Adding or removing columns
- Creating indexes
- Data migrations
- Any change that should only run once
Example File¶
-- upgrade
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- rollback
DROP TABLE IF EXISTS users;
How They Work¶
- Jetbase reads all
V*files and sorts them by version - Compares with applied migrations in the database
- Applies pending migrations in order
- Records each migration after successful execution
Repeatable Always (RA__)¶
These migrations run on every upgrade, regardless of whether they've changed.
Filename Format¶
Runs Always migrations donβt use a version number - just a clear, descriptive name!Examples¶
When to Use¶
- Refreshing materialized views
- Rebuilding indexes
- Resetting permissions or roles
- Any operation that needs to run every time
Example File¶
-- upgrade
REFRESH MATERIALIZED VIEW CONCURRENTLY user_statistics;
REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary;
-- Grant permissions
GRANT SELECT ON user_statistics TO readonly_role;
GRANT SELECT ON order_summary TO readonly_role;
-- rollback
-- Usually no rollback needed for RA migrations
How They Work¶
- After versioned migrations complete
- Jetbase runs all
RA__*files - Every
RA__file runs on every upgrade
Tip
Keep RA__ migrations idempotent (safe to run multiple times).
Repeatable On Change (ROC__)¶
These migrations run only when the file content has changed since the last run.
Filename Format¶
Runs On Change migrations donβt use a version number - just a clear, descriptive name!Examples¶
When to Use¶
- Stored procedures
- Database functions
- Triggers
- Views (non-materialized)
- Any code that can be safely re-created
Example File¶
-- upgrade
CREATE OR REPLACE FUNCTION calculate_order_total(order_id INTEGER)
RETURNS DECIMAL AS $$
BEGIN
RETURN (
SELECT SUM(price * quantity)
FROM order_items
WHERE order_items.order_id = $1
);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- rollback
DROP FUNCTION IF EXISTS update_timestamp();
DROP FUNCTION IF EXISTS calculate_order_total(INTEGER);
How They Work¶
- Jetbase calculates a checksum of the file
- Compares with the stored checksum from last run
- If different (or never run), executes the migration
- Updates the stored checksum
Why Use ROC Over V?¶
For functions and procedures, you often want to:
- Edit the same file as the function evolves
- Avoid creating many versioned migrations for small changes
- Keep related code together in one file
Compare:
With Versioned Migrations:
V20251225.100000__create_calc_total_function.sql
V20251226.100000__update_calc_total_v2.sql
V20251227.100000__update_calc_total_v3.sql
V20251228.100000__fix_calc_total_bug.sql
With Repeatable On Change:
Execution Order¶
When you run jetbase upgrade, migrations execute in this order:
- Versioned migrations β In version order (oldest first)
- Repeatable On Change β Files that have changed
- Repeatable Always β All RA files
[Upgrade Start]
β
βββ V20251225.100000__create_users.sql
βββ V20251225.110000__create_orders.sql
βββ V20251225.120000__add_index.sql
β
βββ ROC__stored_procedures.sql (if changed)
βββ ROC__functions.sql (if changed)
β
βββ RA__refresh_views.sql
βββ RA__update_permissions.sql
β
[Upgrade Complete]
Choosing the Right Type (Use Versioned migrations for almost all use cases!)¶
Use Versioned (V) When:¶
- Making schema changes (CREATE, ALTER, DROP)
- Migrating data between tables
- Changes that must run exactly once
- Order of execution matters
Use Repeatable Always (RA__) When:¶
- Operations need to run every deployment
- Refreshing cached/computed data
- Maintenance tasks
Use Repeatable On Change (ROC__) When:¶
- Managing stored procedures/functions
- Creating / updating views