spin-migrate

Crates.iospin-migrate
lib.rsspin-migrate
version0.0.1
created_at2026-01-10 02:00:54.821901+00
updated_at2026-01-10 02:00:54.821901+00
descriptionDatabase migration library for Spin WASM applications
homepage
repositoryhttps://github.com/halzy/spin-migrate
max_upload_size
id2033305
size73,007
Benjamin Halsted (halzy)

documentation

README

spin-migrate

A lightweight database migration library for Spin WASM applications.

Installation

[dependencies]
spin-migrate = "0.0.1"

Usage

use spin_migrate::{migrations, run_migrations};
use spin_sdk::sqlite::Connection;

const MIGRATIONS: &[spin_migrate::Migration] = migrations! {
    "001_create_users" => "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)",
    "002_create_posts" => "CREATE TABLE posts (id INTEGER PRIMARY KEY, user_id INTEGER)",
    "003_add_index" => "CREATE INDEX idx_posts_user ON posts(user_id)",
};

fn setup_database() -> Result<(), spin_migrate::MigrationError> {
    let conn = Connection::open_default()?;
    let applied = run_migrations(&conn, MIGRATIONS)?;
    println!("Applied {applied} migrations");
    Ok(())
}

One Migration = One SQL Statement

Due to limitations in Spin's SQLite API (single-statement execution only), each migration must contain exactly one SQL statement. Create separate migrations for multiple statements:

// Correct: separate migrations
migrations! {
    "001_create_users" => "CREATE TABLE users (id INTEGER PRIMARY KEY)",
    "002_create_posts" => "CREATE TABLE posts (id INTEGER PRIMARY KEY)",
}

// Wrong: multiple statements in one migration
migrations! {
    "001_create_tables" => "CREATE TABLE users (...); CREATE TABLE posts (...)",
}

API

Function Description
run_migrations(conn, migrations) Run all pending migrations, returns count applied
all_migrations_applied(conn, migrations) Check if all migrations have been applied
get_applied_migrations(conn) List all applied migration names
get_pending_migrations(conn, migrations) Get migrations that haven't been applied yet
validate_migration_order(migrations) Verify migrations are in lexicographic order

Testing

The crate supports rusqlite for testing outside of Spin:

[dev-dependencies]
spin-migrate = { version = "0.0.1", features = ["rusqlite"] }
rusqlite = "0.37"
#[test]
fn test_migrations() {
    let conn = rusqlite::Connection::open_in_memory().unwrap();
    run_migrations(&conn, MIGRATIONS).unwrap();
    assert!(all_migrations_applied(&conn, MIGRATIONS).unwrap());
}

Limitations

  • Each migration must be a single SQL statement
  • No transaction support (Spin SDK limitation - see issue #2286)
  • No down migrations / rollback

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Commit count: 1

cargo fmt