Skip to content

OLC & ODCS

OLC complements the Open Data Contract Standard (ODCS) — it doesn't compete with it. ODCS is the excellent, widely-adopted standard for describing a data contract; OLC adds the executable, lakehouse-scoped layer that runs it. They're two points on the same axis, with a round trip between them, and the reference framework is deliberately ODCS-interoperable so you never have to choose.

The short version

ODCS standardises the agreement · OLC standardises the execution · the reference framework runs both. Use ODCS to publish and agree on a data product across teams and catalogs; use OLC to run it — validate, quarantine, mask, materialize. You never have to choose.

Two layers of one data product

They're not rivals — they stack. ODCS is the business + semantic agreement; OLC is the engineering + execution contract that carries it out:

flowchart BT
    ODCS[Open Data Contract Standard<br/>business + semantic agreement<br/>ownership · semantics · terms · SLA] --> DP[Data product]
    OLC[Open Lakehouse Contract<br/>engineering + execution contract<br/>SQL rules · materialization · engine · incremental] --> DP
    RT[OLC-compatible framework] --> OLC
    E1[Spark] --> RT
    E2[DuckDB] --> RT
    E3[Polars] --> RT
    F[Delta / Iceberg / DuckLake] --> E1
    F --> E2
    F --> E3

By concern

Concern ODCS Open Lakehouse Contract
Data-product metadata ✅ defines basic
Schema ✅ defines ✅ enforces
Ownership / stakeholders ✅ defines reference / integrate
Business semantics ✅ defines reference / integrate
Terms / SLA ✅ defines enforced at runtime
Quality expectations ✅ describes executable checks
PII classification ✅ classifies masking at runtime
SQL rules some representation core design principle
Materialization (merge / append / overwrite)
Table format (Delta / Iceberg / DuckLake)
Engine execution (Spark / DuckDB / Polars)
Cross-engine portability not its role core objective
CI behaviour validation-oriented contract execution

Read it as: ODCS says what the data product is and promises; OLC says how that promise is executed and enforced on a lakehouse. Where they overlap (schema, quality, SLA, PII), ODCS declares and OLC enforces at runtime — the same intent, one described, one executed.

Round-trip interop

The reference framework imports ODCS and can export back to it, so the two aren't a fork in the road:

from lakelogic.core.models import DataContract

contract = DataContract.from_odcs("orders.odcs.yaml")  # ingest an ODCS contract
# ... run it: validate, quarantine, materialize ...
odcs = contract.to_odcs()  # emit ODCS back out

There's also a CLI export (lakelogic export-odcs) in the reference framework.

Two contracts, one framework model

The most powerful mode isn't converting one to the other — it's letting each own what it's best at, and resolving both into a single framework model. The reference framework validates either, and can run OLC with an ODCS agreement alongside:

lakelogic validate product.odcs.yaml          # validate the agreement
lakelogic validate product.olc.yaml           # validate the execution contract
lakelogic run product.olc.yaml \              # run OLC, resolving the ODCS agreement
  --data-contract product.odcs.yaml            #   (proposed)
flowchart TB
    subgraph CONTRACTS[Two contracts · one data product]
      direction LR
      ODCS["ODCS agreement<br/>Ownership · semantics · schema<br/>Quality expectations · SLA"]
      OLC["OLC execution contract<br/>Engine · materialization · SQL<br/>Incremental behaviour · runtime quality"]
    end

    ODCS --> M["Reference framework model<br/>resolves both contracts"]
    OLC --> M
    M --> X["Execute the data product"]

    class ODCS,OLC olc-flow-card
    class M olc-flow-model
    class X olc-flow-outcome

The ODCS document stays the organisation's data-product agreement; the OLC file is the executable lakehouse implementation. Neither duplicates the other.

Proposed: reference an ODCS contract from OLC

A future OLC version may let a contract point at its ODCS agreement instead of restating it, so ownership/semantics/schema live once (in ODCS) and execution lives in OLC:

version: 1.0.0
data_contract: { standard: odcs, ref: ./customer.odcs.yaml }   # ← proposed binding
info: { title: Customer, target_layer: gold }
materialization: { strategy: merge, format: iceberg }
quality:
  row_rules:
    - { name: valid_customer, sql: "customer_id IS NOT NULL" }
This data_contract: binding and the --data-contract flag are proposed — not in the v1 schema yet. Today, use the round-trip (from_odcs / to_odcs).

Native vocabulary, ODCS aliases

OLC keeps its native vocabulary lean — the field names that map directly to executable behavior. Where ODCS uses different names for the same concept, they're accepted as aliases on import, so an ODCS-authored contract validates and runs without a manual rewrite. You don't have to choose one dialect at authoring time.

When to use which

  • Publishing an agreement across teams or orgs, feeding a catalog, or getting governance sign-off? ODCS is the lingua franca — describe it there.
  • Building the data product — enforcing quality, masking PII, materializing to a lakehouse, and wanting the contract to be the pipeline? Author (or import) an OLC and run it.
  • Both? Import ODCS → run as OLC → export ODCS. The descriptive and executable worlds stay in sync through the round trip.

Not either/or

OLC being broader than ODCS is a scope statement, not a value judgment. ODCS is excellent at what it targets. OLC targets the executable superset needed to actually produce and govern the dataset the contract describes.