Most migration tools assume a single process running at a time, and fail silently when that assumption breaks. dbwarden enforces mutual exclusion at the database level, using whatever locking primitive the backend provides natively. The lock is part of the execution contract, not an optional wrapper around it.
PostgreSQL uses a session-scoped advisory lock, which is released automatically if the connection drops. MySQL and MariaDB use named user locks with a configurable timeout. SQLite uses BEGIN IMMEDIATE, which acquires a write lock on the database file for the entire migration run. ClickHouse, which has no session-scoped locks, uses a lease row with a fencing token and a configurable TTL.
Before anything executes, migrate acquires the lock and writes an observable status row. A second runner sees the status, reads the holder diagnostics, and fails immediately instead of racing the first migration. The status row records the holder identity, PID, host, execution ID, migration version, and health state, so an operator can tell who is running and whether they are still making progress.
$ dbwarden lock-status --database primary
Migration lock status
State: RUNNING
Health: HEALTHY
Holder: deploy-worker-3 (PID 12345)
Migration: V042
Acquired: 2026-09-13T14:30:00Z-- PostgreSQL: session advisory lock
-- Released on connection close, even after crash
-- SQLite: BEGIN IMMEDIATE
-- Write lock held for entire migration run
-- ClickHouse: lease with fencing token
-- TTL-based expiry, heartbeat renewal