SchemaQuench turns fragile, step-by-step scripts into safe, declarative releases-so every deployment is boring, predictable, and fast.
SchemaQuench is a state-based, opinionated database migration tool inspired by the principles of infrastructure-as-code tools like HashiCorp's Terraform. It enables you to define the desired end state of your Postgres databases using metadata and applies these definitions to target servers, ensuring consistency and repeatability across environments. We refer to this process as quenching.
Traditional migration scripts track changes over time but can become cumbersome and error-prone, especially in complex environments. SchemaQuench offers a declarative approach, focusing on the desired final state rather than the sequence of changes. This methodology:
TemplateOrder contains all your templates in the order they need to be
quenched.
template.json to find the
correct database(s) to apply against, along with version validation and stamping scripts.
You can use Command Line Options to specify the log file location or an alternate config file.
See the SchemaQuench Walkthrough to help you get started with the tool.
Start by defining a small subset of your database objects. Gradually expand as you gain confidence, ensuring that each step is manageable and verifiable.
SchemaQuench processes a product in two layers: product-level orchestration and per-database quenching. Understanding this sequence helps you place scripts in the correct slots and troubleshoot failures.
For each database matched by a template, SchemaQuench runs these steps in order:
Use Checkpointing with the --ResumeQuench flag
to resume interrupted deployments from the last successful step, rather than starting over.
The "Kindle the Forge" step deploys helper objects into a "SchemaSmith" schema in each target database. These objects are used internally during the quench process and are safe to leave in place between runs.
ExecuteOrDebugQuoteColumnListQuoteIndexColumnListStripParenWrappingFormatJsonMissingTableAndColumnQuenchModifiedTableQuenchMissingIndexesAndConstraintsQuenchIndexOnlyQuenchTableQuenchGenerateTableJsonValidateTableOwnershipFixupTableOwnershipFixupIndexOwnershipCompletedMigrationScripts — Prevents duplicate migration script executionProductOwnership — Records which product owns each table and indexSchemaQuench writes dual-stream log files (Progress + Errors) and diagnostic SQL files when table quench steps fail. These debug files contain the exact SQL that was attempted, making failures easy to reproduce.
Logging & Exit Codes covers log file locations, backup behavior, debug SQL file names, exit codes, and platform-specific logging details including PostgreSQL NOTICE filtering.
SchemaQuench tracks object ownership through a "SchemaSmith"."ProductOwnership" table with columns for Schema, TableName, IndexName, and ProductName. This table:
SchemaQuench tracks errors at multiple levels: script-level, database-level, template-level, and product-level. A script failure is logged and the quench continues to the next script. Repeated failures at higher levels can cause the quench to abort the current database or template while still processing others.
Infrastructure objects and quench procedures use PostgreSQL idempotency patterns: CREATE ... IF NOT EXISTS, DROP ... IF EXISTS, and INSERT ... ON CONFLICT DO NOTHING/UPDATE. This means re-running KindleTheForge is always safe.
When SchemaQuench detects that a table should be dropped (it was once defined in the product but has been removed), it checks for a function named "SchemaSmith"."CustomTableDrop". If found, it calls the function with the schema and table name as parameters and skips the actual drop.
Similarly, "SchemaSmith"."CustomTableRestore" is called near the beginning of each quench to restore previously custom-dropped tables. These hooks let you delay drops, perform custom backups, or implement whatever your process requires.
Say you are widening a column from INT to BIGINT.
On the surface, that is a simple alter table script, however, what if that column
participates in a generated column, a rule, or a view?
You would have to drop those constructs, make your change, and put them back on. That is a lot of bookkeeping for a simple change. SchemaQuench handles all of that for you. You change the type in the table's JSON and SchemaQuench handles the dependencies. See Forge Deeper with SchemaQuench for details.
We now support renaming tables and columns. See defining tables for more details.