Schedule icon
Webhook icon
Assert icon
Request icon
Script icon
Set icon
If icon
Pause icon
Fail icon
Log icon
SlackIncomingWebhook icon

Write-Audit-Publish (WAP) and Atomic Merge Gate for Apache Iceberg with Project Nessie

Implement Write-Audit-Publish (WAP) for Apache Iceberg in Project Nessie. Audit branch diffs, track commit drift in KV, and atomically merge into production.

Categories
CloudDataInfrastructure

Project Nessie provides Git-like transactional catalog semantics (branches, tags, commits, and zero-copy merges) for Apache Iceberg tables and views. This capability makes Nessie the premier choice for implementing Write-Audit-Publish (WAP) patterns on modern Lakehouses running on AWS S3, Google Cloud Storage, or MinIO.

In production data lakes, batch ingestion pipelines (Spark, Flink, or DuckDB) write updates to an isolated Nessie staging branch (e.g., etl_batch_staging). Before publishing this data to the production main branch, the lakehouse architecture must ensure that:

  1. Upstream production writes haven't created excessive commit drift or conflicting table states.
  2. The number of added, updated, or deleted Iceberg tables conforms to expected change thresholds.
  3. Data Stewards and Platform Engineers have an explicit sign-off checkpoint before production schemas advance.
  4. Upon successful merge, the ephemeral staging branch is cleanly deleted so catalog reference trees do not sprawl.

This blueprint automates the audit and publish phases of the WAP cycle. It inspects catalog differences via Nessie REST v2 API, tracks branch drift and pending status in Kestra KV, provides an interactive pause gate for operator approval, issues the atomic merge call, verifies the new production HEAD hash, prunes the staging branch, and broadcasts confirmation to Slack.

How it works

  1. Pre-flight Assertion: validate_inputs (io.kestra.plugin.core.execution.Assert) verifies that branch names, API endpoint URLs, and safety thresholds are valid.
  2. Branch Reference Resolution: get_target_branch_ref and get_source_branch_ref query the Nessie REST v2 API to obtain current HEAD hashes for both branches.
  3. Catalog Diff and Drift Audit: diff_and_audit_branch (io.kestra.plugin.scripts.python.Script) queries /trees/{target}@{hash}/diff/{source}@{hash} to identify all added, modified, and deleted Iceberg tables, calculates commit drift against target history, and compares against prior snapshots in Kestra KV.
  4. KV State Persistence: update_branch_tracker_kv (io.kestra.plugin.core.kv.Set) records the evaluated branch state and pending run counters in Kestra KV.
  5. Approval Gate: If changes are ready and auto_merge is armed, pause_for_operator_approval (io.kestra.plugin.core.flow.Pause) halts execution until an operator confirms approved: true.
  6. Atomic Merge Execution: execute_nessie_merge (io.kestra.plugin.core.http.Request) invokes POST /trees/{target}/history/merge with fromRefName and fromHash to atomically advance production tables.
  7. Post-Merge Verification: verify_merge_commit re-queries the target branch to verify the HEAD hash advanced, failing loudly via assert_target_advanced if the catalog remained unchanged.
  8. Ephemeral Branch Cleanup: delete_staging_branch calls DELETE /trees/{source_branch} with the expected hash to cleanly prune the completed ETL branch.
  9. Audit Trail and Notification: Saves the final WAP audit manifest into Kestra KV and posts a rich confirmation card to Slack.
  10. Error Handling: A flow-level errors block dispatches an alert to Slack if Nessie connectivity or merge execution encounters an unhandled exception.

What you get

  • Automated discovery and classification of table additions, modifications, and deletions between Nessie branches.
  • Protection against stale merges via commit drift thresholds and table count limits.
  • Interactive human-in-the-loop approval gate before touching production data catalogs.
  • Zero-downtime, zero-copy atomic promotion of Iceberg metadata into production.
  • Automatic pruning of ephemeral ETL branches to maintain a clean catalog namespace.
  • Persistent KV audit trail of all lakehouse promotions.

Who it's for

  • Data Lakehouse Engineers and Data Platform Architects managing Apache Iceberg on S3, MinIO, or GCS.
  • Analytics Engineers operating dbt, Spark, or Trino pipelines using WAP patterns.
  • Data Stewards requiring visibility and approval authority over production table updates.

Why orchestrate this with Kestra

Nessie exposes raw Git-like REST APIs, but lacks built-in orchestration, approval checkpoints, or historical trend tracking. Running raw curl or shell scripts lacks stateful drift analysis, cannot safely pause for human review, and provides no audit persistence. Kestra combines declarative API requests, isolated Python evaluation, built-in KV persistence, interactive approval gates, and multi-channel alerting into a unified WAP gate.

Prerequisites

  • A running Project Nessie server (version 0.50.0 or higher) exposing the REST v2 API (e.g. http://nessie.internal:19120/api/v2).
  • An auth token or credentials if Nessie is secured with Bearer token authentication.
  • A Slack Incoming Webhook URL for triage and merge confirmation alerts.

Secrets

  • NESSIE_AUTH_TOKEN: Bearer token for authenticating with the Nessie REST API (leave blank if anonymous access is permitted).
  • SLACK_WEBHOOK_URL: Slack Incoming Webhook endpoint for WAP gate alerts.
  • NESSIE_GATE_WEBHOOK_KEY: Secret key protecting the on-demand WAP merge webhook trigger.

Quick start

  1. Configure NESSIE_AUTH_TOKEN, SLACK_WEBHOOK_URL, and NESSIE_GATE_WEBHOOK_KEY in your Kestra namespace secrets.
  2. Import this blueprint and set nessie_url to your Nessie server REST v2 endpoint.
  3. Run a manual execution with dry_run: true to inspect the diff and commit drift between etl_batch_staging and main without mutating any branches.
  4. Review the execution logs, modified table list, and KV snapshot under inputs.cursor_key.
  5. Set dry_run: false and auto_merge: true to trigger active promotion; approve the pause_for_operator_approval task to commit the merge and prune the staging branch.
  6. Enable the periodic_branch_drift_audit schedule trigger for continuous drift monitoring.

How to extend

  • Automated Data Quality Gate: Insert an io.kestra.plugin.duckdb.Query or Soda/Great Expectations task before the approval gate to run automated row count and null checks on the staging branch tables.
  • Multi-Branch Matrix: Expand to support promoting feature -> dev -> staging -> main across a multi-tier lakehouse promotion hierarchy.
  • Rebase Action: Add an automated branch rebase task calling POST /trees/{source}/history/reassign if commit drift is detected.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.