| Crates.io | postgresql-schema-upgrader |
| lib.rs | postgresql-schema-upgrader |
| version | 0.1.2 |
| created_at | 2026-01-04 06:54:40.185544+00 |
| updated_at | 2026-01-11 03:05:52.523019+00 |
| description | A robust, safety-first library for managing PostgreSQL database schema migrations with both sync and async support. |
| homepage | https://github.com/mshamis85/rust-postgresql-schema-upgrader |
| repository | https://github.com/mshamis85/rust-postgresql-schema-upgrader |
| max_upload_size | |
| id | 2021464 |
| size | 117,290 |
A robust, safety-first Rust library for managing PostgreSQL database schema migrations. It supports both synchronous (blocking) and asynchronous (Tokio) execution modes, handles TLS connections via rustls, and enforces strict integrity checks to prevent database corruption.
postgres crate for synchronous contexts.tokio-postgres for asynchronous contexts.SCHEMA, allowing multiple applications to coexist in the same database or providing strict boundary control.rustls.Add the dependency to your Cargo.toml.
[dependencies]
postgresql-schema-upgrader = { version = "0.1.0", features = ["postgres"] }
[dependencies]
postgresql-schema-upgrader = { version = "0.1.0", features = ["tokio-postgres"] }
Enable the tls feature to support SslMode::Require.
[dependencies]
postgresql-schema-upgrader = { version = "0.1.0", features = ["tokio-postgres", "tls"] }
The library expects a flat directory containing your migration files. Nested directories are not allowed to ensure a linear history.
Rules:
000_init.sql).0 and increment sequentially without gaps (0, 1, 2, ...).Example:
upgraders/
├── 000_initial_schema.sql
├── 001_add_users.sql
└── 002_add_orders.sql
Each file can contain multiple upgrader steps. Steps are separated by a header line starting with --- . Segregating complex migrations into smaller steps allows for finer-grained control and easier recovery.
Rules:
--- <ID>: <Description>0 and increment sequentially without gaps.Example (000_initial_schema.sql):
--- 0: Create Users Table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
--- 1: Create Posts Table
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
title VARCHAR(100)
);
--- 2: Add Index
CREATE INDEX idx_users_username ON users(username);
Once an upgrader (e.g., File 0, Step 1) has been applied to a database, it is locked.
The library validates the integrity of the migration history on every run. If it detects that a file on disk differs from what was recorded in the database, it will return an error and refuse to proceed. This feature prevents "history rewriting" which can lead to catastrophic drift between environments.
You can confine your application's data to a specific schema. This is highly recommended for microservices sharing a database instance.
Use the PostgresUpgraderOptions builder to set the target schema. The library can also create the schema for you if it doesn't exist.
Each upgrader step (everything under a --- ID: header) is executed in its own transaction. If a step fails (e.g., syntax error), the transaction is rolled back, ensuring your database is never left in a half-migrated state.
use postgresql_schema_upgrader::{upgrade_blocking, PostgresUpgraderOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let connection_string = "host=localhost user=postgres password=secret dbname=mydb";
// Configure options
let options = PostgresUpgraderOptions::builder()
.schema("my_app_schema") // Isolate to this schema
.create_schema(true) // Create it if missing
.build();
// Applies upgraders from the "./upgraders" folder
upgrade_blocking("./upgraders", connection_string, &options)?;
println!("Schema upgraded successfully!");
Ok(())
}
use postgresql_schema_upgrader::{upgrade_async, PostgresUpgraderOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let connection_string = "host=localhost user=postgres password=secret dbname=mydb";
let options = PostgresUpgraderOptions::builder()
.schema("my_app_schema")
.create_schema(true)
.build();
// Applies upgraders from the "./upgraders" folder
upgrade_async("./upgraders", connection_string, &options).await?;
println!("Schema upgraded successfully!");
Ok(())
}
The library includes a CLI tool for managing migrations and verifying connections from the terminal.
Install the CLI tool using cargo:
cargo install postgresql-schema-upgrader
Apply migrations from a directory:
# Using a connection string
postgresql-schema-upgrader upgrade --connection-string "host=localhost user=postgres dbname=mydb" --path ./upgraders
# Using individual parameters
postgresql-schema-upgrader upgrade --host localhost --user postgres --database mydb --path ./upgraders
# With optional schema and TLS
postgresql-schema-upgrader upgrade --connection-string "..." --schema my_app --create-schema --tls
Verify the database is reachable:
postgresql-schema-upgrader check-connection --connection-string "..."
postgresql-schema-upgrader check-connection --host localhost --user postgres --database mydb --tls
The CLI supports the following environment variables:
DATABASE_URL: Default for --connection-stringPGPASSWORD: Default for --passwordIf you have the tls feature enabled, you can enforce SSL requirements:
use postgresql_schema_upgrader::{upgrade_async, PostgresUpgraderOptions, SslMode};
let options = PostgresUpgraderOptions::builder()
.ssl_mode(SslMode::Require)
.build();
upgrade_async("./upgraders", connection_string, &options).await?;