New to Kestra?
Use blueprints to kickstart your first workflows.
Audit orders, customers, and payments tables nightly with Soda and Kestra. One scan, several SodaCL check blocks, and a Discord digest with failed counts.
Per-pipeline quality checks catch what each pipeline breaks; nobody watches the tables in between. This blueprint runs one scheduled io.kestra.plugin.soda.Scan over several tables at once, each with its own SodaCL block inside a single checks map, and posts a Discord digest every night with the failed and total check counts. Because the scan runs with allowFailure: true, the digest posts on bad nights too, which is exactly when it matters, while a scan that cannot run at all raises its own alert through the errors block.
seed_warehouse (io.kestra.plugin.jdbc.duckdb.Queries) creates and refreshes small orders, customers, and payments tables in the DuckDB file at warehouse_path. It exists so the blueprint runs anywhere; a real warehouse is already populated by your load pipelines.audit_scan (io.kestra.plugin.soda.Scan) receives the connection through the configuration map, which must define a data source named kestra, and one SodaCL block per table through the checks map: row counts everywhere, missing_count on the columns joins depend on, duplicate_count on the customer key. The requirements list adds soda-core-duckdb.allowFailure: true converts failed checks into a WARNING state, so the flow always reaches the digest instead of dying before reporting.send_digest (io.kestra.plugin.discord.DiscordIncomingWebhook) computes the failed-check count from the per-check outcome fields in {{ outputs.audit_scan.result.checks }} with a jq filter, and posts it alongside the total count and the hasFailures and hasWarnings flags, one comparable line per night.errors block alerts when the audit itself cannot run, and a disabled-by-default Schedule trigger runs the audit at 02:00 after the load window closes.A warehouse audit needs a scheduler, a container to run Soda in, digest formatting, and its own failure alerting. Kestra provides all four: the Schedule trigger sets the cadence, the Scan task ships the Soda container so nothing is installed on workers, the digest is built from structured task outputs rather than parsed logs, and the errors block guarantees a broken audit is louder than a failing table.
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.duplicate_count(customer_id) < 0 and rerun to see the failed count rise while the digest still posts.seed_warehouse, and enable the nightly_audit trigger.configuration map at Snowflake, BigQuery, or Postgres with credentials from {{ secret('...') }}, and add soda-core-snowflake, soda-core-bigquery, or soda-core-postgres to requirements.checks for <table> blocks; the digest counts adapt automatically.