Execution History
Every database operation noorm performs is recorded. When a change runs, a build executes, or files get deployed, that execution goes into the history log with who ran it, when, how long it took, and whether it succeeded.
This gives you an audit trail for compliance, a debugging tool for failures, and a reference for understanding what happened to your database.
What Gets Tracked
noorm records three types of operations:
| Type | Description | Trigger |
|---|---|---|
| change | Change execution | change run, change ff, change next, change revert, change rewind |
| build | Full schema rebuild | run build |
| run | Individual file execution | run file, run directory |
Each record captures:
- Name - Which change, build, or file was executed
- Direction - Forward (
change) or rollback (revert) - Status -
pendingwhile the operation is in flight, thensuccess,failed,reverted, orstale - Who - The identity that ran it (name and email)
- When - Timestamp of execution
- Duration - How long it took in milliseconds
- Checksum - Hash of the executed files
- Error - If failed, what went wrong
File-level details are also preserved. For a change with three SQL files, you can see exactly which file succeeded, which failed, and which were skipped.
Viewing History in the TUI
Navigate to history from the changes menu. Press g from home, then h for history.
+- Execution History --------------------------------------------+
| |
| Total: 47 Changes: 32 Builds: 10 Runs: 5 |
| Success: 45 Failed: 2 |
| |
| > [OK] [CHANGESET] 2025-01-15-add-verification 2 hours ago |
| [OK] [BUILD] schema-build 3 hours ago |
| [OK] [CHANGESET] 2025-01-14-add-user-roles yesterday |
| [ERR] [RUN] seed-data.sql yesterday |
| [OK] [CHANGESET] 2025-01-10-init-schema last week |
| |
| +------------------------------------------------------------+|
| | 2025-01-15-add-verification ||
| | By: Alice <alice@example.com> ||
| | Duration: 1.24s ||
| | Press Enter to view file details ||
| +------------------------------------------------------------+|
| |
| [Enter] View Files [Esc] Back |
+----------------------------------------------------------------+The summary bar shows totals by type. Color-coded status indicators make it easy to spot failures:
- Green
[OK]- Success - Red
[ERR]- Anything else
The list only separates success from not-success. The per-file detail view adds a yellow [-] for skipped files.
Arrow keys move through the list. The detail panel at the bottom shows who ran the selected operation and how long it took.
History Detail View
Press Enter on any record to see file-level execution details:
+- File Executions (2025-01-15-add-verification) ----------------+
| |
| Total: 3 Success: 2 Failed: 1 |
| |
| > [OK] 001_create-tokens-table.sql (0.4s) |
| [OK] 002_add-user-column.sql (0.3s) |
| [ERR] 003_add-index.sql (0.5s) |
| |
| +------------------------------------------------------------+|
| | File Details ||
| | Path: changes/2025-01-15-.../change/001_create-tokens... ||
| | Checksum: 8f4a2b3c9d1e... ||
| +------------------------------------------------------------+|
| |
| [Esc] Back |
+----------------------------------------------------------------+For failed files, the detail panel shows the error message:
| +------------------------------------------------------------+|
| | File Details ||
| | Path: changes/2025-01-15-.../change/003_add-index.sql ||
| | Checksum: 3b7c8d2a4f5e... ||
| | Error: relation "users" does not exist ||
| +------------------------------------------------------------+|This is invaluable for debugging. You can see exactly which file failed, what the error was, and what files succeeded before it.
Headless Mode
For CI/CD pipelines and scripts, use the headless command:
noorm change historyUnlike the TUI screen, this command returns change operations only. Builds and file runs live in the same tracking tables but do not appear here.
Output:
Execution History: 20 records
2025-01-15-add-verification - success (1/15/2025, 2:30:00 PM)
2025-01-14-add-user-roles - reverted (1/14/2025, 4:15:00 PM)
2025-01-10-init-schema - success (1/10/2025, 9:05:00 AM)With JSON output for parsing:
noorm change history --json{
"success": true,
"history": [
{
"id": 42,
"name": "2025-01-15-add-verification",
"direction": "change",
"status": "success",
"executedAt": "2025-01-15T14:30:00.000Z",
"executedBy": "Alice <alice@example.com>",
"durationMs": 1240,
"errorMessage": null,
"checksum": "8f4a2b3c9d1e..."
},
{
"id": 41,
"name": "2025-01-14-add-user-roles",
"direction": "revert",
"status": "success",
"executedAt": "2025-01-14T16:15:00.000Z",
"executedBy": "CI Pipeline <ci@company.com>",
"durationMs": 320,
"errorMessage": null,
"checksum": "3b7c8d2a4f5e..."
}
]
}The id is what noorm change history-detail and the TUI drill-down use to fetch the per-file records for an operation.
Limit the number of records (default 20):
noorm change history --count 50Filtering by Type
The TUI history screen shows all three operation types by default. The summary bar helps you understand the distribution:
Total: 47 Changes: 32 Builds: 10 Runs: 5Type indicators make scanning easy:
| Indicator | Color | Meaning |
|---|---|---|
[CHANGESET] | Cyan | Change execution |
[BUILD] | Blue | Full schema rebuild |
[RUN] | Magenta | Individual file execution |
In the list, you can quickly spot operation types by color before reading the name.
Understanding History Entries
Each history entry tells a complete story. Here's how to read them:
Who Ran It
The identity shows who executed the operation:
By: Alice <alice@example.com>In CI/CD, this might be:
By: GitHub Actions <actions@github.com>Identity is captured from git config or explicitly set via noorm identity. This creates an audit trail for compliance requirements. You can also set a per-config identity override in Configs.
When It Ran
Timestamps appear in relative format in the TUI, rendered by day.js fromNow():
a few seconds ago- Just happened2 hours ago- Recent operationsa day ago- Previous day7 days ago- Within the past weeka month ago- Older records
Relative time is all the TUI shows, however old the record. The JSON output provides ISO timestamps for precise filtering and analysis.
How Long It Took
Duration is shown in seconds:
Duration: 1.24sFor file-level details, you can see individual file timings:
[OK] 001_create-tokens-table.sql (0.4s)
[OK] 002_add-user-column.sql (0.3s)This helps identify slow changes or unexpected performance issues.
What Files Executed
The detail view breaks down each file:
| Status | Icon | Meaning |
|---|---|---|
| Success | [OK] | File executed without errors |
| Failed | [ERR] | Execution threw an error |
| Skipped | [-] | Either a prior run already applied this exact file, or an earlier file in the change failed and this one was never reached |
For skipped files, the skip reason explains why:
[-] setup.sql - already appliedUsing History for Debugging
When something goes wrong, history is your first stop, with one dialect-specific exception. On PostgreSQL a change runs inside a transaction that covers its history rows as well as its DDL, so a failed change rolls back completely and writes nothing to history. Read the error off the failing command there. MySQL, SQL Server, and SQLite keep the failed record and everything below applies.
Finding the Failure
Look for red [ERR] indicators in the list. The most recent failure appears near the top.
[ERR] [CHANGESET] 2025-01-16-add-payments 10 minutes agoDrilling into Details
Press Enter to see which file failed:
[OK] 001_create-table.sql (0.3s)
[ERR] 002_add-constraint.sql (0.1s)
[-] 003_add-index.sql - 002_add-constraint.sql failed: ...The third file was never executed because the second one failed, and its skip reason names the culprit. This tells you exactly where to start looking.
Reading the Error
The error message often points directly to the problem:
Error: duplicate key value violates unique constraint "users_email_key"Now you know the issue---there's duplicate data that needs cleaning before the constraint can be added.
Checking Previous Runs
Compare with successful runs of the same change on other environments. Did something change between runs? Did the data differ?
noorm change history --count 100 --json | jq '.history[] | select(.name == "2025-01-16-add-payments")'Recovery Workflow
After fixing the issue:
- Fix the underlying problem (clean data, modify SQL, etc.)
- Re-run the change with
--forceif needed - Check history to confirm success
- Continue with
change fffor remaining changes
History Retention
History is stored in noorm’s change tracking tables, described in Execution. These tables grow with usage.
For long-running projects, consider:
- Periodic exports for archival
- Database maintenance to manage table size
- Separate tracking databases for high-volume environments
The history is per-database, per-config. Each configuration maintains its own execution history.
What's Next?
- Forward & Revert - Applying and rolling back changes
- Changes - Change directory structure and file types
- Teardown - What happens to history after teardown