Shift Left Data Engineering: Quality at the Source

"Shift Left" in data engineering refers to moving data quality, validation, and governance as close to the source (the producer) as possible. In Level 5 of the Data Maturity Lifecycle, this is operationalized through Data Contracts.

1. The Core Philosophy

Traditional data pipelines are reactive: data breaks in the warehouse, and engineers "fix" it downstream. Shift Left makes quality proactive by enforcing expectations before data ever reaches the analytical platform.

Benefits:

2. Concrete Example: The Data Contract

A Data Contract is a versioned, machine-readable specification of the data's schema, semantics, and SLAs.

Example: orders_contract.yaml

contract_version: 1.0.0
dataset_id: sales.orders
owner: checkout_service_team

schema:
  fields:
    - name: order_id
      type: uuid
      description: "Primary key"
    - name: status
      type: string
      enum: [PENDING, COMPLETED, CANCELLED]
    - name: total_amount
      type: decimal(12,2)
      description: "Must be positive"

quality_expectations:
  - name: freshness
    rule: "ingestion_time - event_time < interval '5 minutes'"
  - name: validity
    rule: "total_amount > 0"
  - name: completeness
    rule: "count(order_id) over (partition by event_date) > 1000"

enforcement:
  action: QUARANTINE  # Move failing records to a 'dead letter' table
  notification: slack-alerts-checkout

3. CI/CD Integration

Data Contracts are enforced during the build phase of the producer's service. Using tools like dbt or Great Expectations, validation is baked into the pipeline:

# Example CI step for contract validation
dbt test --select source:raw_orders --vars '{ "enforce_contract": true }'

If the producer attempts to deploy a change that violates the orders_contract.yaml, the CI/CD pipeline fails, preventing the "dirty" data from entering the Silver layer.

4. Consumer-Driven Contracts (CDC)

In this pattern, the consumer defines their requirements (e.g., "I need a field user_zip to be a 5-digit string").

  1. Consumer submits a contract request.
  2. Producer reviews and accepts the contract.
  3. The platform generates a "Contract Test" that runs against the producer's output.

This ensures that the producer is explicitly aware of who is using their data and for what purpose, preventing accidental breakage during upstream migrations.


See Also: