When your production MySQL database hits millions of rows, a simple ALTER TABLE ADD COLUMN can lock the table for hours — blocking all reads and writes. Zero-downtime schema migration tools solve this by rewriting the table in the background while serving traffic from the original table, then swapping them atomically.
This guide compares three proven approaches: gh-ost (GitHub’s triggerless migration tool), pt-online-schema-change (Percona’s established trigger-based tool), and MariaDB Online DDL (built-in non-blocking DDL). We’ll cover architecture, performance, production deployment, and help you pick the right tool for your workload.
Why Self-Host Your Schema Migration Tooling
Running schema migrations as part of your CI/CD pipeline requires reliable, auditable tools that you control. SaaS migration platforms introduce vendor lock-in, network latency to your database, and compliance concerns. Self-hosted migration tools:
- Run close to your database — no network hop between the migration tool and MySQL
- Integrate with your existing deployment pipeline — Jenkins, GitHub Actions, GitLab CI
- Respect data sovereignty — schema change logic never leaves your infrastructure
- Are open source — inspectable, auditable, and free to modify
- Support air-gapped environments — critical for financial and healthcare sectors
How Online Schema Migration Works
All three tools follow the same fundamental pattern, though their implementations differ:
- Create a ghost table — a copy of the original table with the desired schema changes
- Copy existing rows — migrate data from the original to the ghost table in small batches
- Capture changes — track inserts, updates, and deletes on the original table during the copy
- Apply delta — replay captured changes onto the ghost table
- Atomic swap — rename the ghost table to replace the original in a single transaction
The key difference lies in how they capture changes: triggers (pt-online-schema-change), binary log parsing (gh-ost), or native storage engine support (MariaDB Online DDL).
gh-ost: GitHub’s Triggerless Migration Tool
gh-ost (13,318 stars on GitHub) was developed by GitHub engineers to solve the problems they encountered with trigger-based migration tools at scale. It uses the MySQL binary log to capture changes instead of triggers, eliminating trigger-related overhead and lock escalation issues.
Architecture
gh-ost connects to MySQL as a replica, reads the binary log to detect row changes, and applies them to the ghost table. This triggerless approach means:
- No trigger overhead — no additional write amplification on the source table
- Safe to pause and resume — you can throttle, stop, and restart migrations mid-flight
- Audit-friendly — every change is logged and traceable through the binary log
- Production-tested at GitHub scale — handles tables with billions of rows
Installation
| |
Running with Docker
| |
Production Command
| |
Key flags explained:
--assume-rbr— skip binlog format verification if you know row-based replication is enabled--cut-over=two-step— safer atomic swap that holds a shared lock briefly instead of an exclusive lock--panic-flag-file— create this file to immediately abort the migration--throttle-flag-file— create this file to pause the migration (remove to resume)--throttle-query— a SQL query that, when returning rows, causes throttling--serve-sketch-port— exposes a web UI showing migration progress
pt-online-schema-change: Percona’s Established Tool
pt-online-schema-change (1,476 stars) is part of the Percona Toolkit — a battle-tested collection of MySQL administration utilities. It uses MySQL triggers to capture changes during the table copy phase.
Architecture
pt-online-schema-change creates three triggers on the source table (INSERT, UPDATE, DELETE) that replay each change onto the ghost table. This approach has been production-tested for over a decade:
- Trigger-based change capture — reliable and well-understood behavior
- Chunked row copying — configurable chunk sizes to control load
- Built-in safety checks — detects foreign keys, replication topology, and disk space issues
- Dry-run mode — preview the migration without making changes
- Progress reporting — ETA and rows-per-second metrics
Installation
| |
Docker Deployment
| |
Production Command
| |
Key flags explained:
--chunk-size— number of rows to copy per iteration (adjust based on row size)--chunk-time— target time per chunk (adjusts chunk-size dynamically)--max-load— pause migration when server load exceeds these thresholds--critical-load— abort migration when load exceeds these critical thresholds--check-slave-lag— pause if replica lag exceeds--max-lag(default: 1 second)--no-drop-old-table— keep the original table as a backup after migration
MariaDB Online DDL: Built-In Non-Blocking DDL
MariaDB (7,512 stars) includes native Online DDL support, which allows many schema changes to execute without locking the table. This is the simplest approach when using MariaDB — no external tool required.
How It Works
MariaDB’s storage engine (InnoDB/Aria) handles schema changes internally:
- INPLACE algorithms — modify the table structure without rebuilding the entire table
- INSTANT operations — some changes (like adding a column at the end) complete in milliseconds
- Concurrent DML — reads and writes continue during the schema change
- No external dependencies — no separate tool, no binary log parsing, no triggers
Supported Operations
| Operation | Algorithm | Blocks Reads | Blocks Writes |
|---|---|---|---|
| ADD COLUMN (end of table) | INSTANT | No | No |
| ADD COLUMN (middle of table) | INPLACE | No | No |
| DROP COLUMN | INPLACE | No | No |
| ADD INDEX | INPLACE | No | No |
| DROP INDEX | INPLACE | No | No |
| MODIFY COLUMN (same type) | INPLACE | No | Briefly |
| CHANGE COLUMN (different type) | COPY | Yes | Yes |
| RENAME TABLE | INSTANT | No | No |
| ADD FOREIGN KEY | INPLACE | No | No |
| ADD PRIMARY KEY | COPY | Yes | Yes |
Configuration
Enable Online DDL in your MariaDB configuration:
| |
Usage Examples
| |
Docker Compose for MariaDB with Online DDL
| |
Comparison Table
| Feature | gh-ost | pt-online-schema-change | MariaDB Online DDL |
|---|---|---|---|
| Change Capture | Binary log parsing | Triggers | Storage engine native |
| Database Support | MySQL, MariaDB, Percona | MySQL, MariaDB, Percona | MariaDB only |
| Triggers Required | No | Yes (3 per table) | No |
| Foreign Key Support | Yes (with flags) | No (must disable first) | Yes |
| Pause/Resume | Yes | Limited | No |
| Throttle Control | Flag file + SQL query | Load-based thresholds | No |
| Replica Awareness | Can check replica lag | Built-in lag checking | Built-in replication |
| Dry Run | Yes (--test-on-replica) | Yes (--dry-run) | Yes (EXPLAIN ALTER) |
| Web UI | Yes (Sketch port) | No | No |
| Language | Go | Perl | C++ (built-in) |
| GitHub Stars | 13,318 | 1,476 | 7,512 |
| Last Updated | March 2026 | April 2026 | April 2026 |
| Table Lock Duration | Milliseconds (two-step) | Milliseconds | None (INPLACE) / Brief (COPY) |
| Disk Space Required | ~2x table size | ~2x table size | Varies by operation |
| Best For | Large tables (billions of rows) | Standard MySQL environments | MariaDB-only stacks |
Choosing the Right Tool
Use gh-ost when:
- You have tables with billions of rows where trigger overhead matters
- You need fine-grained throttle control (flag files, SQL queries, rate limiting)
- You want the ability to pause and resume long-running migrations
- Your team prefers triggerless architecture for safety
- You want visibility through the web UI during migrations
Use pt-online-schema-change when:
- You’re running MySQL or Percona Server (not MariaDB)
- You want mature, battle-tested tooling with 10+ years of production use
- You need replica lag awareness built into the tool
- Your DBA team is already familiar with Percona Toolkit
- You want automatic safety checks for foreign keys, triggers, and disk space
Use MariaDB Online DDL when:
- You’re running MariaDB (the operation is built-in, zero overhead)
- You want zero external dependencies — no tool installation needed
- Your schema changes are supported operations (most common DDL is supported)
- You prefer simplicity — just run
ALTER TABLEnormally - You need INSTANT operations for adding columns (sub-millisecond)
Production Best Practices
1. Always Test on a Replica First
| |
| |
2. Set Up Panic and Throttle Mechanisms
| |
3. Monitor During Migration
| |
4. Plan Rollback Strategy
| |
For related reading, see our PostgreSQL high availability comparison for database reliability patterns, MySQL backup strategies for data protection, and database migration tools guide for schema versioning workflows.
FAQ
What is the difference between gh-ost and pt-online-schema-change?
gh-ost uses MySQL binary log parsing to capture changes (triggerless), while pt-online-schema-change uses MySQL triggers. gh-ost has no trigger overhead and supports pausing/resuming migrations, making it better suited for very large tables. pt-online-schema-change has been in production longer and has more built-in safety checks.
Can I use gh-ost with MariaDB?
Yes, gh-ost works with MariaDB as long as binary logging is enabled in ROW format. Use the --assume-rbr flag if the binlog format check fails. gh-ost connects as a replica and reads the binary log regardless of whether the source is MySQL or MariaDB.
Does MariaDB Online DDL support all ALTER TABLE operations?
No. Operations like adding a PRIMARY KEY or changing a column to an incompatible data type require the COPY algorithm, which locks the table. Most common operations — adding/dropping columns and indexes — support INPLACE or INSTANT algorithms that don’t block reads or writes.
What happens if the migration fails halfway through?
With gh-ost, you can resume from where it stopped using the --resume flag. With pt-online-schema-change, you can safely re-run the same command — it detects the partially copied ghost table and continues. Both tools leave the original table untouched during the migration, so a failure never corrupts your data.
How much disk space do these tools require?
All three approaches need approximately 2x the table size in free disk space — the original table plus the ghost table being built. MariaDB Online DDL with the INSTANT algorithm requires minimal additional space (just metadata changes). Always ensure at least 20% free disk space before starting any migration.
Can I throttle migrations during peak hours?
gh-ost supports flag-file throttling (--throttle-flag-file) and SQL-based throttling (--throttle-query). pt-online-schema-change supports load-based throttling via --max-load (pauses when Threads_running exceeds the threshold). MariaDB Online DDL does not support throttling — it runs at full speed.
Do these tools work with replication setups?
Yes. Both gh-ost and pt-online-schema-change can check replica lag and pause the migration if replicas fall behind. Use --check-slave-lag for pt-online-schema-change and --test-on-replica or --assume-master-host for gh-ost. MariaDB Online DDL replicates the ALTER TABLE statement to replicas, which execute it independently.