Webhook icon
Schedule icon
Write icon
ValidateJsonSchema icon
Switch icon
JsonToIon icon
IonToParquet icon
Log icon
SlackIncomingWebhook icon
If icon
Fail icon

JSON Schema Data Contract Validation and Parquet Lake Landing Quarantine

Enforce JSON Schema contracts on event streams with Kestra, convert valid records to Parquet, and isolate contract violations into dead-letter quarantine.

Categories
Data

Data pipelines frequently suffer from silent schema drift, missing mandatory fields, and unexpected data types introduced by upstream microservices or third-party webhooks. When unvalidated JSON lands directly into data lakes or analytical warehouses, downstream dbt transformations, Spark jobs, and Trino/DuckDB queries fail abruptly hours later during production reporting cycles.

This workflow implements a declarative Data Contract Gate for streaming and batch event ingestion. It validates incoming JSON payloads against a strict JSON Schema (Draft-07), bifurcates compliant data from malformed records, serializes verified events into columnar Apache Parquet format, and routes contract breaches into an isolated quarantine storage location accompanied by diagnostic Slack alerts.

How it works

  1. Batch Ingestion & Staging: An incoming JSON payload is received either via real-time Webhook intake (webhook_event_intake) or automated nightly schedule (nightly_batch_schedule). The stage_incoming_payload task writes the raw batch into Kestra internal storage.
  2. Contract Evaluation: The validate_contract task uses io.kestra.plugin.serdes.json.ValidateJsonSchema to check the dataset against the declared JSON Schema contract without failing execution (failOnInvalid: false). It enforces strict field requirements, UUID formats, ISO-8601 timestamps, enum values, and numeric thresholds.
  3. Operational Conformance Routing: A Switch task evaluates outputs.validate_contract.valid:
    • COMPLIANT Branch:
      • Converts verified JSON objects into Amazon Ion binary representation via io.kestra.plugin.serdes.json.JsonToIon.
      • Compiles the Ion stream into Snappy-compressed columnar Apache Parquet using io.kestra.plugin.serdes.parquet.IonToParquet.
      • Logs landing metrics including total records processed, Parquet storage URI, and contract version.
    • BREACHED Branch:
      • Quarantines the invalid payload into internal storage with complete violation metadata (failing JSON paths, error codes, and execution ID) via quarantine_payload.
      • Dispatches an actionable alert to Slack containing exact schema failure locations (instanceLocation) and violated rules.
      • Optionally fails the pipeline via enforce_contract_failure if strict enforcement (fail_on_contract_breach: true) is required.

What you get

  • Zero Silent Lakehouse Corruption: Guarantees that only structurally validated records conforming to data contracts reach curated Parquet storage layers.
  • Dead-Letter Quarantine: Prevents unparseable payloads from being discarded; corrupt records are stored with full context for inspection and reprocessing.
  • Native Columnar Serialization: Transforms raw nested JSON directly into compact, query-optimized Apache Parquet files without requiring external compute clusters.
  • Field-Level Error Diagnostics: Identifies the exact offending JSON path (e.g. [1].payload.amount) and constraint failure reason rather than generic parsing errors.

Who it's for

  • Data Platform Engineers: Protecting central S3, MinIO, or Google Cloud Storage data lakes from upstream schema changes.
  • Analytics Engineers: Ensuring dbt models and warehouse tables ingest only validated, high-quality event streams.
  • Backend & Event-Driven Architects: Implementing Shift-Left data contracts between microservices and analytics teams.

Why orchestrate this with Kestra

Building data contract gates with custom cron scripts or Lambda functions requires writing fragile validation code, managing temporary disk buffers for format conversion, and maintaining separate alerting scripts. Kestra orchestrates the entire contract lifecycle declaratively:

  • Native SerDes Plugins: High-performance streaming conversions (ValidateJsonSchema, JsonToIon, IonToParquet) execute inside Kestra without requiring Python dependencies or heavyweight Spark clusters.
  • Dynamic Flow Routing: Seamlessly branches between lakehouse compilation and dead-letter quarantine using built-in condition logic.
  • Multi-Modal Triggers: Accepts streaming payloads via Webhook triggers while maintaining scheduled backfill capabilities on the same pipeline.

Prerequisites

  • A running Kestra instance with access to the plugin-serdes and plugin-notifications plugins (included in standard Kestra distributions).
  • Network access from Kestra to your Slack workspace (for incident notifications).

Secrets

  • SLACK_WEBHOOK_URL: Slack Incoming Webhook URL used to publish contract breach incident notifications to your data operations channel.

Quick start

  1. Configure the SLACK_WEBHOOK_URL secret in your Kestra namespace or key-value store.
  2. Import this workflow into your Kestra instance.
  3. Run an initial test execution using the default compliant payload to verify Parquet compilation.
  4. Test the quarantine mechanism by submitting an invalid payload (e.g., negative amount or missing event_id) to watch the workflow route records to dead-letter quarantine and dispatch a Slack alert.
  5. Wire upstream microservices or message queues to post JSON batches to the generated Webhook URL.

How to extend

  • Cloud Object Storage Landing: Add an io.kestra.plugin.aws.s3.Upload or io.kestra.plugin.gcp.gcs.Upload task to ship compiled Parquet files directly to production S3/GCS buckets.
  • Confluent Schema Registry Integration: Swap the inline schema for registry configuration in ValidateJsonSchema to pull versioned schemas dynamically from Karapace or Confluent Schema Registry.
  • Automated Replay: Implement an approval-gated subflow that allows data engineers to patch quarantined JSON records and re-inject them into the pipeline.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.