Schedule icon
Fail icon
Query icon
Get icon
Query icon
OutputValues icon
If icon
Log icon
SlackIncomingWebhook icon
Pause icon
Set icon

Reload a ClickHouse dimension table from Postgres with an atomic swap and automatic rollback

Refresh a ClickHouse table from Postgres via a shadow copy, audit parity, require approval on big shrinks, EXCHANGE TABLES atomically and auto-rollback.

Categories
Data

A full reload of a ClickHouse dimension usually means TRUNCATE plus INSERT, so dashboards querying it in that window see an empty or half-filled table. This blueprint loads a shadow table next to the live one, proves it matches Postgres, then swaps the two names with one atomic EXCHANGE TABLES.

How it works

  1. validate_inputs rejects non-identifier input (everything is interpolated into SQL) and require_atomic_engine stops unless the target database uses the Atomic engine.
  2. read_state loads the fingerprints of the last publish. audit_source (Postgres) and audit_live (ClickHouse) compute row count, distinct keys and a checksum. refresh_gate skips unchanged sources, but still repairs a live table that drifted from the last publish.
  3. create_shadow and load_shadow build <table>__refresh with the ClickHouse postgresql() table function while readers keep using the live table. verdict compares the audited shadow with the source, and fail_on_parity_mismatch and fail_on_empty_source stop the run before anything is published.
  4. A reload shrinking the table by more than max_shrink_pct waits in the approval Pause. Timeout fails the run, so an ignored request never publishes.
  5. swap_tables runs EXCHANGE TABLES, audit_published re-reads the live name, and rollback_gate swaps back and fails the run if it differs from the audited shadow. Only a verified publish reaches save_state.

What you get

  • Readers never see an empty or partial dimension.
  • Parity proof between Postgres and the shadow before any swap.
  • An approval gate on suspicious shrinks, automatic rollback, and the previous data kept under the shadow name until the next run.

Who it's for

  • Analytics and platform engineers serving dashboards from ClickHouse dimensions copied out of Postgres.

Why orchestrate this with Kestra

The safety is ordering and state: audit, branch, pause for a person, mutate, verify, undo. Kestra keeps fingerprints in KV between runs, holds the approval without a worker, and runs the failure handler on any step.

Prerequisites

  • ClickHouse with an Atomic database and an existing live table matching the source columns.
  • A Postgres read user reachable from both the worker and the ClickHouse server.
  • Locally, the clickhouse/clickhouse-server and postgres Docker images on one network.

Secrets

  • POSTGRES_USERNAME and POSTGRES_PASSWORD: read-only Postgres user, also passed to postgresql().
  • CLICKHOUSE_USERNAME and CLICKHOUSE_PASSWORD: user allowed to create, drop and exchange tables.
  • SLACK_WEBHOOK_URL: approval requests and results.

Quick start

  1. Create the secrets and the live ClickHouse table.
  2. Execute once with inputs adjusted to your table.
  3. Delete rows in Postgres to hit the shrink approval path, then resume or reject.
  4. Remove disabled: true from the trigger.

How to extend

  • Reload dictionaries sourced from this table after swap_tables.
  • Loop over several dimension tables with io.kestra.plugin.core.flow.Loop.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.