New to Kestra?
Use blueprints to kickstart your first workflows.
Enforce table schemas as contracts with Soda and Kestra. SodaCL schema checks fail on missing or forbidden columns and alert Discord on drift.
Schema drift rarely announces itself; it shows up as a dbt model that stopped compiling, a dashboard full of NULLs, or an export that silently dropped a column. This blueprint makes the schema itself a tested contract: io.kestra.plugin.soda.Scan runs a SodaCL schema check listing the columns that must exist and the legacy columns that must not. Drift fails the check, the check fails the task, and the errors block posts a Discord alert naming the table and pointing at the exact failing condition, one loud failure at the source instead of many confusing ones downstream.
load_orders (io.kestra.plugin.jdbc.duckdb.Queries) creates the orders table with the contracted columns in the DuckDB file at warehouse_path. It exists so the blueprint runs anywhere; in production the table is whatever your loads produce.schema_scan (io.kestra.plugin.soda.Scan) receives the connection through the configuration map, which must define a data source named kestra, and a SodaCL schema check through the checks map: when required column missing lists the columns every consumer depends on, and when forbidden column present lists columns that were deliberately removed and must not return. The requirements list adds soda-core-duckdb.errors block, so drift and alert cannot be separated by a forgotten notification task.confirm_contract logs the passing verdict from {{ outputs.schema_scan.result }}, leaving a per-execution record that the contract held at scan time.Schedule trigger keeps the detection window within one load cycle.A schema check is only useful on a cadence, with alerting, and with a record of every verification. Kestra provides the schedule, routes the failure to Discord through the errors block with no extra wiring, and preserves each verdict as structured outputs in the execution history. The Scan task ships the Soda container image, so the check runs identically on any worker with nothing installed.
warehouse_path input) visible to the task containers. For production warehouses, swap the configuration map to Snowflake, BigQuery, or Postgres and add the matching soda-core-* package to requirements.DISCORD_WEBHOOK_URL: Discord incoming webhook URL.DISCORD_WEBHOOK_URL secret to your Kestra namespace.legacy_id to the required-columns list and rerun to watch the drift path: failed check, failed task, Discord alert.hourly_contract_check trigger.when wrong column type to the schema check to pin column types as well as names, using the type names your warehouse reports.when schema changes: any for change-over-time detection; this variant compares against previous scans and requires a Soda Cloud connection in the configuration map.configuration map at Snowflake, BigQuery, or Postgres with credentials from {{ secret('...') }}, and add the matching soda-core-* package to requirements.