Skip to content

postgres: opt-in checksum ledger to skip unchanged schema files#1844

Open
ns-kosti wants to merge 2 commits into
mainfrom
postgres/skip-unchanged-schema
Open

postgres: opt-in checksum ledger to skip unchanged schema files#1844
ns-kosti wants to merge 2 commits into
mainfrom
postgres/skip-unchanged-schema

Conversation

@ns-kosti

@ns-kosti ns-kosti commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

What

Adds an opt-in track_schema_checksums intent flag to the OSS Postgres database provider. When enabled, each schema file's checksum is recorded in a foundation.schema_checksums table and the file is only re-applied when its contents change, instead of being re-applied on every ns deploy.

Why

The provider currently re-applies every .sql file on every deploy. Schema files are expected to be idempotent (e.g. fn_ensure_table, CREATE INDEX IF NOT EXISTS), so this is safe but wasteful. The checksum table lets us skip files that haven't changed.

Design

  • Opt-in, default false — existing databases are unaffected until they enable it.
  • Checksum = sha256: + hex of the raw file bytes. No canonicalization, so any byte change re-applies; this avoids the correctness risk of a SQL-aware normalizer at the cost of an occasional harmless re-run.
  • Table = foundation.schema_checksums(path TEXT PRIMARY KEY, checksum TEXT, updated_at TIMESTAMPTZ).
  • Written only after a successful apply, so updated_at stays constant across redeploys when nothing changed.
  • Path validation — empty and duplicate paths are rejected, since path is the primary key.
  • Single batched read of stored checksums (WHERE path = ANY($1)); reads and writes retry on retryable errors.
  • Logs each schema file it applies (skipped files are silent).

Caveat

The table records that a file's bytes were applied successfully once; it is not an assertion that the live schema matches the file. With the fn_ensure_* helpers, editing a definition changes the checksum (so the file re-runs) but the helper may still no-op against an existing object. It's a re-execution cache.

Tests

Unit tests cover checksum determinism, byte-sensitivity, the sha256: prefix, and path validation. End-to-end skip/re-apply coverage is tracked in #1845.

ns-kosti added 2 commits June 24, 2026 16:00
## What

Adds an opt-in `track_schema_checksums` intent flag to the OSS Postgres database provider. When enabled, each schema file's checksum is recorded in a `foundation.schema_checksums` table and the file is only re-applied when its contents change, instead of being re-applied on every `ns deploy`.

## Why

The provider currently re-applies every `.sql` file on every deploy. Schema files are expected to be idempotent (e.g. `fn_ensure_table`, `CREATE INDEX IF NOT EXISTS`), so this is safe but wasteful. The checksum table lets us skip files that haven't changed.

## Design

- **Opt-in, default false** — existing databases are unaffected until they enable it.
- **Checksum** = `sha256:` + hex of the raw file bytes. No canonicalization, so any byte change re-applies; this avoids the correctness risk of a SQL-aware normalizer at the cost of an occasional harmless re-run.
- **Table** = `foundation.schema_checksums(path TEXT PRIMARY KEY, checksum TEXT, updated_at TIMESTAMPTZ)`.
- **Written only after a successful apply**, so `updated_at` stays constant across redeploys when nothing changed.
- **Path validation** — empty and duplicate paths are rejected, since `path` is the primary key.
- **Single batched read** of stored checksums (`WHERE path = ANY($1)`); reads and writes retry on retryable errors.
- **Logs** each schema file it applies (skipped files are silent).

## Caveat

The table records that a file's bytes were applied successfully once; it is not an assertion that the live schema matches the file. With the `fn_ensure_*` helpers, editing a definition changes the checksum (so the file re-runs) but the helper may still no-op against an existing object. It's a re-execution cache.

## Tests

Unit tests cover checksum determinism, byte-sensitivity, the `sha256:` prefix, and path validation. End-to-end skip/re-apply coverage is tracked in #1845.
- storedChecksums now uses ReturnFromReadWriteTx for retry/backoff instead
  of a hand-rolled loop with repeated retryable-error classification.
- ApplyWithHelpers branches on the positive track-checksums intent for
  readability; behavior is unchanged.
@ns-kosti
ns-kosti force-pushed the postgres/skip-unchanged-schema branch from 09b7528 to a46ed8e Compare June 24, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant