Database Migrations in Rust: Overview of Tools and Libraries
When developing any application, sooner or later the need arises to change the database structure. Adding new columns, creating indexes, or renaming tables — all of this requires careful schema version management. In the Rust ecosystem, there are several mature solutions for performing migrations. In this article, we will review the main approaches and libraries available for database schema management tasks.
Why are migrations needed?
Migrations allow you to:
- Version changes — each migration is a separate file with a version number.
- Automate deployment — apply and roll back changes during deployment.
- Work in a team — all developers synchronize the schema locally.
- Avoid errors — migrations protect against accidental data modification.
Main tools for migrations in Rust
1. Diesel Migration (built into Diesel ORM)
Diesel is the most popular ORM for Rust. It provides a built-in migration engine via the diesel_cli CLI utility.
Key features:
- Generation of migration files with SQL queries.
- Support for PostgreSQL, MySQL, SQLite.
- Commands:
migration generate,migration run,migration redo. - Automatic tracking of applied migrations.
Example of creating and applying a migration:
# Install CLIcargo install diesel_cli --no-default-features --features postgres
# Create a new migrationdiesel migration generate create_users
# Two SQL files will appear in the migrations/ folder:# up.sql — code to apply# down.sql — code to roll back
# Run the migrationdiesel migration runContents of up.sql:
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW());down.sql:
DROP TABLE IF EXISTS users;2. SQLx migrate (part of the SQLx ecosystem)
SQLx is an async SQL database driver. Its migration subsystem works without an ORM, using only plain SQL scripts.
Distinctive features:
- Support for PostgreSQL, MySQL, SQLite, MSSQL.
- Integration with CLI and programmatic execution from code.
- Ability to use Rust code for checks before migration.
- Automatic integrity verification (file hashing).
Example of programmatic migration execution in Rust:
use sqlx::migrate::Migrator;use sqlx::PgPool;
#[tokio::main]async fn main() -> Result<(), sqlx::Error> { let pool = PgPool::connect("postgres://user:pass@localhost/db").await?; // Specify the path to the migrations folder let migrator = Migrator::new(std::path::Path::new("./migrations")).await?; // Run all pending migrations migrator.run(&pool).await?; println!("Migrations completed successfully!"); Ok(())}Structure of the migrations/ folder:
migrations/├── 20231001_initial.sql├── 20231002_add_email_index.sql└── 20231003_create_roles.sqlEach file contains plain SQL, for example:
-- 20231001_initial.sqlCREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), username TEXT NOT NULL UNIQUE);3. SeaORM Migrator (part of SeaORM)
SeaORM is a modern async ORM that offers its own migration system, SeaORM Migrator. It allows you to write migrations in Rust rather than SQL, which d
Also in library
MetricsKit — Swift App Monitoring for iOS/macOS
Monitoring Swift Applications: Libraries and Tools for iOS/macOS
Image Processing and Editing in TypeScript: Jimp, Sharp, Canvas
Swagger/OpenAPI Generation for Java: Best Libraries
Working with ZIP/archives in TypeScript: a complete guide to JSZip and adm-zip