Skip to content

Releases: muandane/grizzle

v0.2.0 - Observability, Safety & Production Hardening

Choose a tag to compare

@muandane muandane released this 14 Oct 14:33
v0.2.0
6d35670

Overview

Grizzle v0.2.0 brings production-grade observability, high-concurrency safety guards, multi-tenant automation, hot-path engine performance improvements, and the official Grizzle GitHub Action for CI/CD pipelines.


🛡️ Lock Contention Pre-Flight & Gating

  • Active Lock Contention Inspection: Queries pg_locks and pg_stat_activity to detect long-running transactions and queries on target tables before executing DDL steps requiring strong table locks (AccessExclusiveLock, ShareUpdateExclusiveLock).
  • Advisory Warnings & Fail-on-Contention: Defaults to actionable advisory logs with conflicting PIDs, usernames, running queries, and durations. When --fail-on-contention is enabled, retries with exponential backoff up to LockTimeout, failing closed with LockContentionError if contention does not clear.

🌐 External Dev Database URL for Shadow Compilation

  • Non-Privileged Production Users: Compile declarative shadow schemas against an external development database (--dev-url / Options.DevDatabaseURL), eliminating the requirement for CREATE SCHEMA privileges on restricted live target databases.
  • Fail-Closed Operator Guidance: When target database users lack schema creation privileges and no dev URL is configured, Grizzle returns actionable guidance citing --dev-url and GRANT CREATE ON DATABASE with zero silent fallbacks.

📊 OpenTelemetry Observability & Zero-Lock Readiness Probes

  • Dedicated otelgrizzle Package: Zero-dependency core with first-class OTel metrics in github.com/muandane/grizzle/otelgrizzle:
    • migration_duration_seconds (Float64Histogram): labeled by dialect and status (applied, failed, noop).
    • drift_detected (Int64Counter): counter for detected schema drift and hash mismatches.
    • lock_wait_seconds (Float64Histogram): time spent acquiring database locks.
  • Zero-Lock Readiness Probe (grizzle.IsReady): High-throughput health/readiness probe for Kubernetes pods inspecting grizzle_history without holding advisory locks, table mutations, or schema drift.

🔄 Composite Primary Key Keyset Backfill

  • $N$-Column Composite Primary Keys: Generalizes expand/contract keyset pagination using SQL row-value comparisons (pk1, ..., pkN) > ($1, ..., $N) and tuple IN batches across PostgreSQL and SQLite.
  • Index Verification & Resumption: Verifies index ordering before keyset traversal begins and seamlessly resumes interrupted backfills without duplicating or skipping rows.
  • 53% Allocation Reduction: Hoisted scan pointers and pre-allocated parameter builders boosted backfill throughput to 51,644 rows/sec.

🏢 Multi-Tenant Schema Patterns

  • Dynamic Schema Discovery (--target-schema-pattern): Automatically discovers and synchronizes PostgreSQL schemas matching LIKE patterns (e.g. tenant_%) in deterministic alphabetical order.
  • System & Internal Isolation: Automatically excludes PostgreSQL internal schemas (pg_%, information_schema) and Grizzle shadow schemas (_grizzle%). Schema additions and removals participate in Plan.Hash() for drift protection.

⚡ Official Composite GitHub Action (action.yml)

  • Native CI/CD Automation: Run lint, check, plan, diff, and apply in GitHub Actions workflows with zero Go toolchain overhead.
  • Fast Pre-Built Binaries: Automatically downloads native pre-compiled release binaries for Linux (amd64/arm64), macOS, and Windows in under 1 second.
  • GitHub Workflow Annotations: Passes --github for inline PR review annotations (::notice, ::error).

🔍 Expanded Declarative SQL Linter

  • docs/LINTER_SPEC.md: Comprehensive review specification defining 80+ schema rules across table design, foreign keys, index hygiene, and security.
  • Initial Strict Rules: Shipped L014 (PrimaryKeyTypeAllowlist), L022 (DisallowReservedKeywords), L044 (RequireBooleanDefault), L047 (DisallowDuplicateIndex), and L048 (DisallowRedundantPrefixIndex) with --profile strict and .grizzle.yaml configuration.

🧪 Nix-Native Concurrency & Chaos Stress Testing

  • Added automated chaos and concurrency scenarios in test/scenarios/ with registered devenv commands:
    • scenario-race: 50 parallel goroutines verifying advisory locking and zero dirty state.
    • scenario-contention: Pre-flight lock contention detection under simulated long-running queries.
    • scenario-chaos: Mid-flight process termination and transaction rollback verification.

What's Changed (Pull Requests)

  • feat(exec): external dev database URL for shadow compilation (#55) by @muandane in #55
  • feat(exec): composite primary key keyset backfill (#56) by @muandane in #56
  • feat(schema): multi-tenant schema patterns via pg_namespace discovery (#57) by @muandane in #57
  • feat(exec): lock contention pre-flight with backoff retry (#58) by @muandane in #58
  • feat(metrics): otelgrizzle metrics and zero-lock readiness probe (#59) by @muandane in #59
  • feat(devenv): add nix-native test scenarios and benchmarks (#61) by @muandane in #61
  • feat(ci): add official GitHub Action and update CHANGELOG for v0.2.0 (#63) by @muandane in #63

Full Changelog: v0.1.0...v0.2.0


Installation

GitHub Actions

- uses: actions/checkout@v7
- uses: muandane/grizzle@v0.2.0
  with:
    command: lint
    schema: schema.sql
    strict: true

Go CLI

go install github.com/muandane/grizzle/cmd/grizzle@v0.2.0

Go Modules

go get github.com/muandane/grizzle@v0.2.0
go get github.com/muandane/grizzle/otelgrizzle@v0.2.0

Pre-Built Binaries

Pre-built standalone binaries for Linux, macOS (Darwin), and Windows (amd64 / arm64) are available in the assets below. Verify integrity using checksums.txt.

v0.1.0 - General Availability

Choose a tag to compare

@muandane muandane released this 13 Oct 20:23
v0.1.0
a7eb8ae

Grizzle v0.1.0 - General Availability (GA)

We are thrilled to announce the General Availability (GA) release of Grizzle v0.1.0 — declarative, zero-downtime database schema migrations for Go, PostgreSQL, and SQLite.

Grizzle replaces error-prone sequential migration scripts with declarative schema management: you declare your desired schema in standard SQL, and Grizzle computes minimal, ordered, and safe DDL migration plans to transition your database to the target state.


Key Highlights

🎯 Declarative Schema Migrations

  • Single Source of Truth: Define your desired schema using clean SQL declarations (CREATE TABLE, CREATE INDEX, CREATE TYPE, etc.).
  • Diff-Driven Execution: Grizzle reverse-engineers the live database catalog, diffs it against your desired schema, and plans the precise topological sequence of non-destructive mutations required.
  • Frozen Plan Hashing: SHA-256 plan digests (Plan.Hash()) guarantee migration determinism, drift protection, and tamper verification.

🛡️ Production & Zero-Downtime Safety

  • Non-Blocking Indexing: Automated CREATE INDEX CONCURRENTLY in PostgreSQL and safe 12-step rebuilds in SQLite. Interrupted builds automatically drop invalid indices (indisvalid=false) and rebuild cleanly.
  • PgBouncer & Connection Pooler Safety: Fast failover (<10ms) detection of transaction-pooling / PgBouncer environments to prevent advisory lock hanging.
  • Deadlock & Block Avoidance: Enforces statement and lock timeouts (statement_timeout, lock_timeout) across all transactional steps.
  • Crash Recovery & Prior-Failure Gating: Stale table cleanup (_grizzle_new_*, _grizzle_tmp_*) and fail-closed boot protection (ErrPriorFailureBlocked) with operational escape hatches (grizzle repair, WithAllowResumePartial).

📦 Multi-Format Migration Exporters

Export declarative plans to static migration files compatible with existing migration runners:

  • golang-migrate (--format migrate / --format golang-migrate): Paired companion artifacts ({timestamp}_{name}.up.sql and {timestamp}_{name}.down.sql) with automatic reverse-down generation.
  • goose (--format goose): Single-file -- +goose Up / -- +goose Down scripts.
  • atlas (--format atlas): Atlas-compatible directory format.
  • Standard SQL (--format sql): Raw up/down SQL files.

🗄️ Comprehensive Database Object Coverage

  • PostgreSQL:
    • Tables, columns, generated columns, defaults, check constraints, foreign keys.
    • Custom types: Enums (with safe in-place values and renames), composite types (ALTER TYPE ... ATTRIBUTE), and range types.
    • Views, materialized views, triggers, and PL/pgSQL functions.
    • Standalone and owned sequences (INCREMENT BY, MINVALUE, MAXVALUE, CYCLE, OWNED BY).
    • Row Level Security (RLS) policies and PostgreSQL role grants.
    • Multi-schema targeting and schema qualify rewrites (TargetSchemas).
  • SQLite:
    • Embedded SQLite support with foreign-key preservation and transaction-safe table rebuilds.
    • Attached database support.

🛠️ Operational CLI Lifecycle

  • grizzle status: Detailed synchronization report and history summary (human-readable and --json).
  • grizzle history: Audit recorded migrations with sort and limit controls.
  • grizzle baseline: Baseline pre-existing production databases without executing DDL.
  • grizzle repair: Mark interrupted or failed migrations as resolved with operator notes.
  • grizzle dump: Reverse-engineer live database catalogs into canonical DDL.
  • grizzle lint: Static DDL linter with configurable safety rules and inline directive suppression (-- grizzle:lint-ignore).

🔌 In-Process Boot Auto-Migration & Observability

  • Embeddable Go library (grizzle.Sync(ctx, db, opts...)) for zero-ops service boots.
  • OpenTelemetry instrumentation package: github.com/muandane/grizzle/otelgrizzle for distributed traces across DDL planning and execution phases.

What's Changed in v0.1.0 (Since v0.1.0-rc5)

  • feat(export): Added golang-migrate export format with paired .up.sql and .down.sql artifacts (#54).
  • feat(postgres): Added fast detection of transaction pooling (PgBouncer) during advisory lock acquisition (ErrTransactionPooling).
  • test(plan): Frozen Plan.Hash() contract and added comprehensive golden tests covering all 71 ChangeType step kinds.
  • test(failover): Added SQLite stale rebuild cleanup and enriched ErrPriorFailureBlocked operator guidance.
  • test(api): Audited root package boundaries to ensure zero internal type leaks and preserved Options.TargetSchema backward compatibility.
  • ci(matrix): Fully certified against PostgreSQL 14, 15, 16, 17, and 18 multi-version test matrix.

Installation

Go CLI

go install github.com/muandane/grizzle/cmd/grizzle@v0.1.0

Go Library

go get github.com/muandane/grizzle@v0.1.0
go get github.com/muandane/grizzle/otelgrizzle@v0.1.0

Pre-Built Binaries

Pre-built binaries for Linux, macOS (Darwin), and Windows (amd64 / arm64) are available in the assets below.
Verify integrity using checksums.txt.

v0.1.0-rc5

v0.1.0-rc5 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 17:48
v0.1.0-rc5
ec87caf

Changelog

  • ec87caf fix(postgres): rewrite target schema qualifiers in single-schema shadow compilation

v0.1.0-rc4

v0.1.0-rc4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 16:04
v0.1.0-rc4
a65669c

Changelog

  • a65669c chore(release): prepare v0.1.0-rc4
  • 8a99732 feat(lifecycle): implement operational lifecycle, onboarding tooling, and developer ergonomics (#53)
  • d1964ba feat(sync): harden in-process auto-migration boot path and test suite (#52)
  • dd019f7 fix(ci): stabilize warm boot latency check and polish readme

v0.1.0-rc3

v0.1.0-rc3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 12 Oct 21:46
v0.1.0-rc3
425d532

Changelog

  • 29a84e8 Fix DBA review issues (#43)
  • 6e62e58 Merge pull request #28 from muandane/chore/goreleaser-formats
  • 089c84e chore(goreleaser): rename archives.format to formats
  • 425d532 chore(release): prepare v0.1.0-rc3
  • 8bc8f49 feat(postgres): manage owned sequences and standalone CREATE SEQUENCE (#29)
  • ad8a183 feat: expression normalization to cut false diffs (#30) and ALTER POLICY role evolution (#33)
  • ff90df7 feat: function signature ordering (#40), SQLite parity lint (#42), and SeedSQL idempotency (#32)
  • 6500ef2 feat: shadow compile error hints, static lint rules, and ALTER POLICY drift
  • a58d045 feat: user-defined types (range, composite, enum renames) and partition hazard polish (#37, #38, #39, #41)
  • 36355b2 fix(schema): gate index header and predicate normalization on index definitions
  • 4fc77f5 fix: remediate delegated review findings across P0-P3
  • c99e78b refactor: apply modern Go ergonomics and address code review findings
  • 7dd683d test(bench): expand benchmark suite and fix testing.TB context initialization

v0.1.0-rc2 — Managed surface + RolesSQL/CatalogSQL

Choose a tag to compare

@github-actions github-actions released this 08 Oct 13:16
v0.1.0-rc2
bd69d9a

Grizzle v0.1.0-rc2

Second release candidate — managed-surface parity plus RolesSQL / CatalogSQL side-channel contracts.

Full changelog: CHANGELOG.md · Docs: README · SAFETY · SPEC

Highlights

Area What shipped
Managed surface Extensions, RLS/policies, functions, procedures, aggregates, triggers, views/matviews, domains, and COMMENT ON are now declarative (diff + apply), not just protected
RolesSQL CREATE ROLE / GRANT side-channel (--roles / Options.RolesSQL); marker-narrow drops; AllowRevoke / AllowDropRole
CatalogSQL Publications + event triggers (--catalog / Options.CatalogSQL); marker-narrow drops
SQLite Named/inline CHECK constraints introspected, emitted on rebuild, and diffed (AllowDropCheck)
Safety / plan Stricter Plan.Hash(); lock/shadow identity no longer in plan artifacts; DryRunVerifyPlan; GENERATED_REWRITE is CRITICAL

Breaking changes (from rc.1)

  • Plan hash format — Plan.Hash() now includes DropPolicy, NonConcurrentIndexes, and SchemaSQL. Previously approved plan artifacts fail ExpectedHash / envelope checks (ErrPlanDrift). Re-plan and re-approve.
  • Plan artifact shape — lock_id, lock_namespace, shadow_schema, and options_digest are removed from the plan document. Lock identity is derived at apply time; shadow schemas are ephemeral per run.
  • GENERATED_REWRITE is CRITICAL — generated-column rewrites require explicit AcceptHazards: GENERATED_REWRITE.
  • Former “protected” objects are managed — drifted views/triggers/functions/etc. now emit plan steps; live-only objects become drops gated by the new AllowDrop* flags and hazard codes.

Notable additions

  • COMMENT ON — table/column comments via obj_description / col_description; clear emits COMMENT_CLEAR (NOTICE)
  • Procedures & aggregates — procedures like functions; aggregates reconstructed from pg_aggregate (DROP+CREATE); share AllowDropFunction + DROP_FUNCTION
  • Domains — base type / nullability / default / CHECK; retype is DROP+CREATE; live drops need AllowDropDomain + DROP_DOMAIN
  • Extensions / RLS / functions / triggers / views — full declarative sync with corresponding AllowDrop* gates
  • Lint L008 / L009 — RLS enabled without policies (WARNING); DML in SchemaSQL (ERROR — use SeedSQL)
  • DryRunVerifyPlan — dry-run an approved plan artifact with envelope + live re-diff; CLI apply --dry-run --plan
  • grizzle.ErrHistoryRecord — typed non-fatal error when DDL applied but history write failed
  • Export Down — goose reversals for policy/RLS/function/trigger/view steps (extension create irreversible by design)

Side channels

# Privileges (PostgreSQL)
grizzle plan  --schema schema.sql --roles roles.sql --out plan.json
grizzle apply --plan plan.json

# Cluster catalog: publications + event triggers (PostgreSQL)
grizzle plan  --schema schema.sql --catalog catalog.sql --out plan.json

See examples/roles-grants/ and examples/catalog-sync/.

CLI at a glance

grizzle plan  --schema schema.sql --out plan.json
grizzle apply --plan plan.json [--accept-hazard CODE ...]
grizzle check --schema schema.sql
grizzle lint  --schema schema.sql          # L001–L009
grizzle apply --dry-run --plan plan.json   # envelope + live re-diff

Exit codes: 0 ok · 1 error · 2 hazard blocked · 3 plan drift · 4 schema drift

Tested engines

PostgreSQL 14–18 · SQLite (embedded)

Install

Download a binary below for your OS/arch, or:

go install github.com/muandane/grizzle/cmd/grizzle@v0.1.0-rc2

Status

Pre-release (rc2). API may still shift before v0.1.0 final. Please file issues for regressions.

v0.1.0-rc.1 — First release candidate

Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 Oct 14:00
v0.1.0-rc.1
7952e0d

Grizzle v0.1.0-rc.1

First public release candidate of Grizzle — a declarative schema migration engine for PostgreSQL and SQLite with hazard gating, plan approval, and multi-pod safety.

Full changelog: CHANGELOG.md · Docs: README · SAFETY · SPEC

Highlights

Area What shipped
PostgreSQL Multi-schema, partitions (RANGE/LIST/HASH), partial/functional indexes, generated columns, CHECK constraints (NOT VALID → VALIDATE), concurrent indexes
SQLite 12-step rebuild with trigger/view preservation, keyset batch copy, savepoint FK checks
Safety Default-deny drops, hazard gates (AcceptHazards), unmanaged dependency protection (views/triggers/functions), session advisory locks + retry
CLI plan / apply / check / lint / seed / export (sql, goose, atlas)
DX Dry-run sandbox, lifecycle hooks, idempotent seeds, expand/contract + --rename (experimental)

CLI at a glance

grizzle plan  --schema schema.sql --out plan.json
grizzle apply --plan plan.json [--accept-hazard CODE ...]
grizzle check --schema schema.sql          # CI drift gate
grizzle lint  --schema schema.sql          # L001–L007
grizzle apply --dry-run                    # live rollback sandbox
grizzle seed  --seed seed.sql

Exit codes: 0 ok · 1 error · 2 hazard blocked · 3 plan drift · 4 schema drift

Notable features in this RC

  • Declarative CHECK constraints (Postgres) — staged like FKs; drops gated by AllowDropCheck
  • Schema lint L001–L007 — including CHECK naming / duplicates / anonymous names
  • Unmanaged fidelity — function/procedure deps via pg_depend + remediation hints
  • ZDM CLI — --expand-contract, repeatable --rename old=new (see examples/expand-contract)
  • Dry-run, hooks, seed, lock retry — production-oriented apply path

Tested engines

PostgreSQL 14–18 · SQLite (embedded)

Install

Download a binary below for your OS/arch, or:

go install github.com/muandane/grizzle/cmd/grizzle@v0.1.0-rc.1

Breaking notes (vs early prototypes)

  • Module path is github.com/muandane/grizzle
  • Options.ExpectedHash removed — pass approval hash via ApplyOpts.ExpectedHash

Status

Pre-release (rc.1). API may still shift before v0.1.0 final. Please file issues for regressions.