# How Omarchy Handles Database Migrations: A Complete Guide to Script-Driven System Evolution

> Omarchy streamlines database migrations with a script-driven system. Discover and execute timestamped SQL scripts easily and ensure atomic updates for robust system evolution. Learn how.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: how-to-guide
- Published: 2026-09-05

---

**Omarchy handles database migrations through a lightweight, shell-based system that uses the `omarchy-migrate` command to discover and execute timestamped scripts in the `migrations/` directory, tracking state in `$XDG_DATA_HOME/omarchy/migrations` and aborting on any error to ensure atomic updates.**

Omarchy, a declarative system configuration framework, manages configuration state changes across releases using a deterministic migration system. Unlike traditional database migration tools that rely on SQL, Omarchy employs **idempotent Bash scripts** executed in strict chronological order to modify system files and configuration. This approach ensures that upgrades are reproducible, testable, and safe, with the `omarchy-migrate` command serving as the central orchestrator for all system state transitions.

## The Migration Architecture and File Structure

Omarchy stores migration logic as executable shell scripts within the `migrations/` directory of the repository. Each script follows a **timestamped naming convention** (for example, [`1788595060.sh`](https://github.com/omacom/omarchy/blob/main/1788595060.sh) or [`1788124236.sh`](https://github.com/omacom/omarchy/blob/main/1788124236.sh)) that encodes execution order chronologically. The `bin/omarchy-migrate` file implements the core discovery engine, scanning this directory and sorting scripts by filename to determine sequence.

This architecture treats system configuration as code, allowing migrations to move files, update drop-in configuration snippets, or modify service definitions. Because the system targets operating system state rather than relational data, migrations use standard Unix utilities and Bash logic instead of SQL statements.

## How the omarchy-migrate Command Discovers and Executes Scripts

When invoked, `omarchy-migrate` performs a deterministic discovery process:

1.  **Scanning**: It identifies all files in the `migrations/` directory matching the `*.sh` pattern.
2.  **Ordering**: It sorts discovered scripts lexicographically by filename, ensuring that timestamp prefixes dictate execution sequence.
3.  **Execution**: It runs each script in a clean environment with `bash -euo pipefail`, causing immediate termination if any command fails or references an undefined variable.

According to the implementation in `bin/omarchy-migrate`, the system enforces **strict error handling**. If any migration script exits with a non-zero status, the entire migration run aborts immediately, preventing partial system modifications that could leave the configuration in an inconsistent state.

```bash

# Run all pending migrations (normally invoked automatically after upgrades)

omarchy-migrate

# Execute with verbose output for debugging

bash -x /usr/local/bin/omarchy-migrate

```

## Tracking Pending and Completed Migrations

Omarchy maintains migration state within the user's data directory to prevent re-execution of successful scripts. After a migration completes with exit code 0, the system records its completion in `$XDG_DATA_HOME/omarchy/migrations`. This state tracking allows the `--pending` flag to identify migrations that have not yet successfully run.

```bash

# List all migrations waiting to be applied

omarchy-migrate --pending

```

The state file mechanism ensures **idempotency** across multiple upgrade attempts; rerunning `omarchy-migrate` only executes scripts that failed or were introduced since the last successful run.

## Integration with System Upgrades

The migration system integrates directly into Omarchy's upgrade pipeline through `bin/omarchy-upgrade-to-quattro`. This script calls `omarchy-migrate` immediately after completing package upgrades, ensuring that configuration adjustments apply before the user session resumes. This sequencing guarantees that binary updates and configuration migrations occur atomically, preventing version mismatches between installed software and system configuration.

The upgrade script's implementation demonstrates that migrations are not manually triggered by users during normal operation, but rather orchestrated automatically as part of the system's self-healing update mechanism.

## User Notification for Pending Migrations

When automatic migration execution fails or requires user intervention, the `omarchy-migrate-notify` command provides feedback. Defined in `bin/omarchy-migrate-notify`, this helper checks for pending migrations using the `--pending` flag and surfaces desktop notifications to alert users that manual action is required.

The repository includes a **systemd user service** at `default/systemd/user/omarchy-migrate-notify.service` that triggers this notification check after the graphical session starts. This ensures that users are promptly informed of any configuration drift that needs resolution without polling the system manually.

## Testing Migration Safety and Idempotency

The test suite validates migration behavior through [`test/shell.d/upgrade-to-quattro-test.sh`](https://github.com/omacom/omarchy/blob/main/test/shell.d/upgrade-to-quattro-test.sh). This test verifies that:

-   Migrations execute in the correct chronological order derived from filenames.
-   The system correctly handles success, failure, and pending states.
-   Scripts are **idempotent**, meaning they can run multiple times without causing errors or unintended side effects.

These automated checks enforce that all contributions to the `migrations/` directory meet safety standards before release, ensuring that community-contributed configuration changes do not destabilize existing installations.

## Writing Custom Migration Scripts

Migration scripts must conform to strict execution standards to maintain system integrity. A valid migration requires the shebang `#!/usr/bin/env bash` and must enable `set -euo pipefail` at the outset. The script should verify preconditions, perform atomic file operations, and exit with status 0 on success.

```bash
#!/usr/bin/env bash
set -euo pipefail

# Example: Migrate legacy configuration to new structure

old_conf="${HOME}/.config/omarchy/old.conf"
new_conf="${HOME}/.config/omarchy/settings.conf"

if [[ -f "$old_conf" ]]; then
    mv "$old_conf" "$new_conf"
fi

# Explicitly exit 0 to mark success

exit 0

```

Scripts should avoid dependencies on external services and must handle cases where previous partial runs may have completed some but not all steps.

## Summary

-   **Discovery mechanism**: The `bin/omarchy-migrate` command scans the `migrations/` directory and sorts scripts by timestamped filenames to determine execution order.
-   **Strict execution**: Every migration runs under `bash -euo pipefail`, with any non-zero exit code aborting the entire migration process to prevent partial updates.
-   **State tracking**: Completed migrations are recorded in `$XDG_DATA_HOME/omarchy/migrations`, enabling the `--pending` flag to identify outstanding work.
-   **Upgrade integration**: The `bin/omarchy-upgrade-to-quattro` script automatically invokes migrations after package updates, ensuring configuration and binaries remain synchronized.
-   **User notifications**: The `bin/omarchy-migrate-notify` helper and corresponding systemd service alert users when manual migration intervention is required.
-   **Validation**: The [`test/shell.d/upgrade-to-quattro-test.sh`](https://github.com/omacom/omarchy/blob/main/test/shell.d/upgrade-to-quattro-test.sh) test suite enforces idempotency and correct ordering for all migration scripts.

## Frequently Asked Questions

### What is the difference between Omarchy migrations and traditional SQL database migrations?

Traditional SQL migrations modify relational database schemas using statements like `CREATE TABLE` or `ALTER COLUMN`, whereas Omarchy migrations are **Bash scripts** that modify system configuration files, move data directories, or update service definitions. Omarchy's approach treats the entire operating system configuration as a versioned state, using shell commands rather than SQL to achieve idempotent system evolution.

### How does Omarchy ensure that migrations run in the correct order?

The system relies on **lexicographic sorting of filenames** within the `migrations/` directory. Developers prefix migration scripts with Unix timestamps (for example, [`1788595060.sh`](https://github.com/omacom/omarchy/blob/main/1788595060.sh)), ensuring that alphabetical order corresponds to chronological execution sequence. The `bin/omarchy-migrate` command implements this sorting logic during the discovery phase, guaranteeing deterministic run order across all installations.

### What happens if a migration script fails during execution?

If any migration returns a non-zero exit code, the `omarchy-migrate` command **immediately aborts** the entire run without attempting subsequent scripts. This fail-fast behavior, enforced by `set -euo pipefail` within the execution environment, prevents partial configuration changes that could corrupt system state. Users must fix the underlying issue and rerun `omarchy-migrate` to complete the pending migrations.

### How can I check which migrations are pending without running them?

Use the `--pending` flag to display a list of migrations that have not yet been recorded as successful in the state file. This command queries `$XDG_DATA_HOME/omarchy/migrations` against the available scripts in the `migrations/` directory, providing a safe way to audit upcoming configuration changes before applying them.