New to Kestra?
Use blueprints to kickstart your first workflows.
Orchestrate idempotent Snowflake upserts with Kestra. Stage a delta file, COPY into staging, and MERGE into the target as one transactional batch.
Apply a batch of changed rows to a Snowflake target table as an idempotent incremental upsert, without ever leaving the target in a half-applied state. This blueprint uploads a delta file to the table's internal stage, resets a transient staging table, COPYs the delta in, and MERGEs into the target with deduplication on the business key, all inside a single Snowflake transaction. If any statement fails, the whole batch rolls back. Reruns are safe because the MERGE is keyed and the dedup keeps only the latest row per key.
io.kestra.plugin.core.http.Download (fetch_delta) pulls a sample CSV delta. Replace this with your real extract (S3, GCS, HTTP, SFTP, dbt artifact, CDC capture, etc.).io.kestra.plugin.jdbc.snowflake.Upload (stage_upload) uploads the file to the target table's internal stage @KESTRA.PUBLIC.%CUSTOMERS under a delta/ prefix with gzip compression.io.kestra.plugin.jdbc.snowflake.Query (ensure_staging) issues CREATE TRANSIENT TABLE IF NOT EXISTS ... LIKE CUSTOMERS as a one-off DDL outside the transaction.io.kestra.plugin.jdbc.snowflake.Queries (merge_upsert) runs with transaction: true and a per-execution queryTag. It DELETEs the staging rows, COPYs the staged delta with ON_ERROR = 'abort_statement', then MERGEs into CUSTOMERS using QUALIFY ROW_NUMBER() OVER (PARTITION BY CUSTOMER_ID ORDER BY UPDATED_AT DESC) to dedup late or duplicate rows.io.kestra.plugin.slack.notifications.SlackIncomingWebhook (notify) posts a confirmation; the alert_on_failure error handler posts a rollback notice if anything fails.Schedule trigger at 0 4 * * * is included but disabled by default.QUALIFY ROW_NUMBER dedup on CUSTOMER_ID / UPDATED_AT.queryTag so every batch is traceable in Snowflake's QUERY_HISTORY.Snowflake Tasks can schedule SQL, but they cannot fetch a delta file from an external system, upload it to an internal stage, and coordinate a multi-statement transaction with retries, Slack alerting, and lineage in one declarative unit. Kestra triggers this flow on a schedule or an event (webhook, file arrival, upstream extract finishing), captures every statement's result, retries transient failures, exposes outputs to downstream tasks, and keeps the full YAML in Git. Pair it with namespace secrets for credentials so nothing is hardcoded.
KESTRA.PUBLIC.CUSTOMERS (keyed by CUSTOMER_ID with an UPDATED_AT column), and grants to create transient tables and write to the table's internal stage.SNOWFLAKE_URL: JDBC URL, for example jdbc:snowflake://<account>.snowflakecomputing.com?warehouse=COMPUTE_WH.SNOWFLAKE_USERNAME: Snowflake user.SNOWFLAKE_PASSWORD: Snowflake password (swap for privateKey for key-pair auth).SLACK_WEBHOOK_URL: Slack incoming webhook URL.@KESTRA.PUBLIC.%CUSTOMERS.fetch_delta with your real extract and point stage_file at the resulting filename.merge_upsert to your schema.Schedule trigger when ready.fetch_delta for io.kestra.plugin.aws.s3.Downloads, io.kestra.plugin.gcp.gcs.Downloads, or an SFTP task to pull deltas from your lake.Webhook or Flow trigger so the upsert fires the moment upstream extract finishes.io.kestra.plugin.core.flow.ForEachItem to parallelize across multiple target tables.password with privateKey (and privateKeyPassword if encrypted) in pluginDefaults.outputs.merge_upsert.outputs and assert thresholds with a follow-up Assert task.