Datatrail
BUYER'S GUIDE - UPDATED AUGUST 2026

Data Contracts: What Is a Data Contract, the Open Data Contract Standard, and Examples

A working guide rather than a manifesto. What goes in a contract, a complete ODCS example you can copy, which tools actually enforce one and at what moment, and the standards change from December 2025 that most articles on this subject have not caught up with.

See the example
Read-only No card to start
Lineage map
Lineage mapped from query history. Read-only connection.
0

Read-only connection. Datatrail never moves or mutates your data.

In short

A data contract is a machine-readable agreement between the producer of a dataset and its consumers, covering schema, semantics, quality rules, ownership, and service level, kept in version control so a breaking change can fail a build. The format to use in 2026 is the Open Data Contract Standard v3.1.0, released 8 December 2025 under the LF AI and Data Foundation, because the competing Data Contract Specification formally deprecated itself in favour of it. Contracts are enforced by tools, not by the YAML: the Data Contract CLI in pipelines and CI, dbt model contracts at build time, a schema registry for streaming, and continuous monitoring for everything no rule anticipated.

Last updated August 2026

// DEC 2025

Read this before you pick a format

There are no longer two competing data contract standards

For about two years, anyone adopting data contracts had to choose between two YAML formats: the Open Data Contract Standard from the Bitol project, and the Data Contract Specification from datacontract.com. Nearly every article, conference talk, and vendor comparison published on this topic frames that choice as still open.

It is not. The Data Contract Specification deprecated itself. Its README carries a deprecation notice reading, verbatim: "With the release of the Open Data Contract Standard v3.1.0, we deprecate the Data Contract Specification in line with our commitment to focus on a single industry standard for data contracts. We have actively contributed to the Open Data Contract Standard in the TSC and will continue to support it." The same notice recommends migrating "within the next few months" and states that the older format will be supported in the Data Contract CLI and Entropy Data only until the end of 2026. Elsewhere the README calls ODCS "the conceptual successor" and "highly recommended".

Three practical consequences. If you are starting now, write ODCS and ignore any tutorial that presents the choice as live. If you already have contracts in the older format, you have until the end of 2026 and the Data Contract CLI has an ODCS export path, so this is a conversion rather than a rewrite. And if a vendor is still marketing support for both as a differentiator, that is a sign their material has not been updated since 2025.

The consolidation is good news for buyers. A single format is what makes tooling interoperable, and it is the difference between a contract being a portable artifact and a contract being lock-in with a YAML extension.

// ODCS 3.1.0

The eleven sections

What actually goes in a data contract

ODCS v3.1.0 defines eleven top-level areas. You are not expected to fill in all of them, and a contract with two sections that people actually maintain beats a contract with eleven that nobody reads. The right-hand column is our view on when each one earns its keep.

Section What it holds When to fill it in
Fundamentals Name, version, owner, domain, status, and the description that tells a human what this dataset is Always. This is the minimum viable contract.
Schema Every object and property, with logical and physical types, plus which fields are required, unique, or primary keys Always. This is what tools check first.
Data quality The rules that must hold: completeness, ranges, freshness, custom SQL, referenced or inline Usually second. Start with three rules, not thirty.
Service-level agreement Frequency, latency, retention, availability, and the time by which data is expected to be there When consumers depend on timing. This is where data SLA lives.
Support and communication The channel a consumer uses to report a problem, and where announcements go Early. A contract nobody can escalate against is a document.
Team Named humans with roles and dates, not a distribution list Early, and it is the field most often left empty.
Roles The access roles a consumer needs and how to request them When access provisioning is part of the promise.
Infrastructure and servers Where the data physically is: platform, host, catalog, schema, table, format When the contract must be machine-resolvable to a real object.
Pricing Cost per unit for chargeback models Rarely. Mostly used where internal chargeback exists.
References Links to documentation, dashboards, and related contracts Whenever the context lives somewhere else.
Custom properties Anything your organization needs that the standard does not model Sparingly. Every custom field is one no tool understands.
// EXAMPLE

A real one, not a fragment

A complete data contract example in ODCS

This is a contract for an orders table a checkout service produces and three analytics teams consume. It is deliberately small. Every field below is part of ODCS v3.1.0, and this file will lint with the Data Contract CLI.

apiVersion: v3.1.0
kind: DataContract
id: 8f4a2c10-3b7e-4c19-9d2a-0f6b5e8c1a44
name: orders
version: 2.1.0
status: active
domain: commerce
dataProduct: checkout
tenant: acme

description:
  purpose: Every completed customer order, one row per order, from checkout.
  usage: Revenue reporting, cohort analysis, finance reconciliation.
  limitations: Excludes abandoned carts and orders voided within 60 seconds.

schema:
  - name: orders
    physicalName: fct_orders
    physicalType: table
    logicalType: object
    properties:
      - name: order_id
        logicalType: string
        physicalType: varchar
        required: true
        unique: true
        primaryKey: true
        description: Immutable order identifier from checkout.
      - name: customer_id
        logicalType: string
        physicalType: varchar
        required: true
      - name: order_total_usd
        logicalType: number
        physicalType: number(18,2)
        required: true
        description: Order total in USD, tax inclusive, excluding shipping.
      - name: placed_at
        logicalType: date
        physicalType: timestamp_ntz
        required: true
        description: UTC. Not the local time of the customer.
      - name: status
        logicalType: string
        physicalType: varchar
        required: true

    quality:
      - rule: nullCheck
        property: order_id
        mustBe: 0
        dimension: completeness
      - rule: duplicateCount
        property: order_id
        mustBe: 0
        dimension: uniqueness
      - rule: validValues
        property: status
        validValues: ['placed', 'paid', 'shipped', 'refunded']
        dimension: validity
      - rule: freshness
        property: placed_at
        mustBeLessThan: 3
        unit: hours
        dimension: timeliness

slaProperties:
  - property: latency
    value: 3
    unit: hours
  - property: frequency
    value: 1
    unit: hours
  - property: retention
    value: 7
    unit: years

team:
  - username: [email protected]
    role: Data Product Owner
    dateIn: '2025-11-03'
  - username: [email protected]
    role: Producer Engineering Lead
    dateIn: '2026-02-17'

support:
  - channel: '#checkout-data'
    tool: slack
    scope: interactive
  - channel: [email protected]
    tool: email
    scope: announcements

servers:
  - server: prod
    type: snowflake
    account: acme-prod
    database: analytics
    schema: commerce

Four things in that file do most of the work, and they are worth calling out because they are the ones teams leave out.

The description block is the only part a human will read voluntarily, and the limitations line prevents more misuse than any quality rule. "Excludes abandoned carts" is the sentence that stops an analyst spending a day reconciling a number that was never meant to reconcile.

The unit and timezone in a description. Note order_total_usd and "UTC, not the local time of the customer". Silent unit and timezone changes break more dashboards than schema changes do, and they pass every structural check ever written because the type never changed.

The SLA block is where a data SLA lives, and it is the section consumers care about most. Latency, frequency, and retention are three lines that answer nearly every question a downstream team would otherwise ask in Slack.

The support channel, which turns the contract from a document into an agreement. A contract with no escalation path is documentation with extra steps.

To generate a first draft rather than typing this from scratch, use the Data Contract CLI import command against an existing table. It reads BigQuery, Glue, JSON Schema, Avro, and SQL DDL, and gives you a schema block that is already correct so the work left is the semantics.

// ENFORCE

The part that is not YAML

Where a data contract is actually enforced

A contract file enforces nothing. Something has to read it and fail something. There are six places that can happen, and they differ enormously in how early they catch a problem and how hard they are to adopt.

Enforcement point Typical tool When it fires The catch
Producer code review Gable Before the change merges The only layer that prevents the breakage rather than reporting it
Streaming produce Confluent Schema Registry Before the message is accepted Structural only. No semantics, no ownership, no SLA.
Pipeline or CI run Data Contract CLI, Great Expectations, Soda Before or after the load, wherever you place it Fails a build. Needs somewhere to run and someone to maintain it.
dbt build dbt model contracts At build time, on the model shape Shape only, and most constraints are informational on cloud warehouses
Warehouse DDL Snowflake, Databricks, BigQuery On write, in theory Mostly not enforced. NOT NULL is the reliable one.
Continuous monitoring Datatrail, Monte Carlo, DataHub assertions After the data lands, on a schedule Catches what nobody wrote a rule for, and names the affected consumers

Read that table from the top down and you get the uncomfortable truth about contract programs: enforcement gets easier to adopt as it gets less useful. Blocking a producer's pull request prevents the incident outright and is the hardest thing in the world to get a software engineering team to agree to. Continuous monitoring after the fact requires nobody's permission and only tells you after the damage is done.

Almost every successful rollout we have seen runs both ends and skips the middle. The gate goes on the two or three datasets where a break is genuinely expensive, and monitoring covers everything else, because you will never write contracts for four hundred tables and you should stop pretending otherwise. That split is the same one behind data quality tools that ask you to declare rules and data observability tools that learn a baseline.

The warehouse DDL row deserves its own warning. Snowflake's constraints documentation is explicit that on standard tables PRIMARY KEY, UNIQUE, and FOREIGN KEY are optional and not enforced, and only NOT NULL is enforced. Databricks behaves the same way, enforcing NOT NULL and CHECK while treating primary and foreign keys as informational. A declared primary key on a Snowflake table is a hint to the optimizer, not a guarantee, and duplicates will land in it without a single error. If you thought DDL was your contract enforcement layer, it is not.

// COMPARE

Side by side

Data contract tools and standards compared

Tool or standard What it is Format it speaks Where it enforces Pricing
Open Data Contract Standard (ODCS) The standard itself, not a product ODCS v3.1.0 YAML Nothing on its own. Tools read it. Free, Apache 2.0
Data Contract Specification The other standard, now deprecated DCS v1.2.1 YAML Nothing on its own Free
Data Contract CLI Open-source tool to lint, test and convert contracts ODCS natively, plus 25+ formats In CI, and against a live data source Free, open source
dbt model contracts Contract enforcement built into dbt dbt YAML, not ODCS At build time, on the model shape Free, dbt Core is Apache 2.0
Soda Data quality checks that grew into a contracts engine SodaCL YAML, with contract support In pipelines and CI, against the warehouse Free tier, Team plan published
Gable Shift-left contract enforcement in code review Its own contract model In the producer's pull request No published pricing
Confluent Schema Registry Contract enforcement for streaming, predating the term Avro, Protobuf, JSON Schema At produce time, on the topic Open source core, Confluent Cloud metered
DataHub Catalog with contracts assembled from assertions Its own contract entity By running assertions against the asset Core free, Cloud unpublished
Snowflake and Databricks native constraints Table constraints in the warehouse itself DDL Mostly not, and this surprises people Included
Datatrail Detects contract breaches and names what they break Reads your dbt manifest and query history Continuously, after the fact, with blast radius Planned, self-serve
Great Expectations (GX Core) Assertion framework, often used to back a contract Python Expectations Wherever you run it in the pipeline Free, Apache 2.0
Atlan, Collibra and Informatica Governance platforms adding contract features Platform-native models Through policy and workflow No published pricing
// 12 ENTRIES

The detail

Every data contract tool, and what it is actually for

01

Open Data Contract Standard (ODCS)

The standard itself, not a product

This is now the industry standard, and as of December 2025 it is effectively the only one. ODCS is a YAML format that describes a dataset as an agreement: who owns it, what its schema is, what quality rules hold, what the service level is, and how to reach the team behind it. Version 3.1.0 was released on 8 December 2025, it carries the media type application/odcs+yaml;version=3.1.0, and the project sits under the LF AI and Data Foundation with Apache 2.0 licensing and roughly 1,075 GitHub stars. Eleven top-level areas make up a contract: fundamentals, schema, references, data quality, support and communication channels, pricing, team, roles, service-level agreement, infrastructure and servers, and custom properties. Only the first two are usually filled in on a first attempt, which is fine. The standard is deliberately additive.

02

Data Contract Specification

The other standard, now deprecated

Read this entry before you follow any tutorial written before 2026. The Data Contract Specification, the OpenAPI-flavoured YAML format from the datacontract.com project, deprecated itself. Its README now opens with a deprecation notice: "With the release of the Open Data Contract Standard v3.1.0, we deprecate the Data Contract Specification in line with our commitment to focus on a single industry standard for data contracts." The same notice recommends migrating within the next few months and says the format will be supported in the Data Contract CLI and Entropy Data only until the end of 2026. The README goes further and calls ODCS "the conceptual successor". Almost every comparison article still frames these two as competing options you have to choose between. That choice was made and announced by one of the two parties, and the category consolidated onto ODCS.

03

Data Contract CLI

Open-source tool to lint, test and convert contracts

The most practical starting point, because it turns a YAML file into something that fails a build. It lints a contract for validity, connects to a data source and runs the schema and quality tests the contract declares, generates a changelog between two versions so you can see what changed, and exports to more than twenty-five formats including dbt models and sources, JSON Schema, Avro, SodaCL, SQL, Terraform, and ODCS itself. Import works the other way, so you can generate a first draft from an existing BigQuery table, Glue catalog, or SQL DDL rather than writing YAML from a blank file. It is healthy and moving fast: version 1.1.0 landed on PyPI on 4 August 2026, and it natively supports ODCS. Python 3.10 to 3.12, with 3.11 recommended.

04

dbt model contracts

Contract enforcement built into dbt

If your transformations already run through dbt, this is the contract enforcement you can turn on this afternoon. Set contract: enforced: true on a model, declare every column name and data type, and dbt runs a preflight check before building: if the query would return a different shape, the build fails rather than shipping the change. dbt-core 1.12.0 shipped on 16 July 2026. Two limits matter and are widely misunderstood. First, it is all or nothing per model, because dbt requires explicit expectations for every column in a contracted model, not just the ones you care about. Second, and more important, most constraints you can declare are not actually enforced by the warehouse. On Snowflake, BigQuery, and Redshift only not_null is enforced; primary_key, foreign_key, and unique are definable and purely informational. Postgres enforces all of them. We wrote up the full matrix in our guide to data contracts in dbt.

05

Soda

Data quality checks that grew into a contracts engine

Soda made the biggest bet of any vendor in this category on contracts being the durable artifact. The soda-core GitHub repository now describes the project as a "Data Contracts engine for the modern data stack", which is a repositioning from data quality testing rather than an addition to it, and Collaborative Data Contracts sit alongside quality checks in the commercial product. Soda Core 4.21.0 was published on 13 August 2026, so this is not a stale rebrand. Check the license before you build on it, though: the v4 release replaced Apache-2.0 with the Elastic License 2.0 in January 2026, and PyPI now declares soda-core Proprietary, which makes it source-available rather than open source. Our Soda alternative page covers what that changes. Checks are written in SodaCL, a YAML language that reads closer to a sentence than to SQL, and the work is pushed down into the warehouse rather than pulling rows out. Soda is also one of very few vendors in the whole data-contract and data-quality space that publishes a price: a free tier, a Team plan at $750 per month, and enterprise quoted separately. The trade is that YAML gets awkward once checks become genuinely complicated.

06

Gable

Shift-left contract enforcement in code review

Gable attacks the problem from the only place it can genuinely be prevented: the application repository where a producer is about to change a field. Rather than checking data after it lands, it inspects the code change, works out which downstream data assets it affects, and comments on the pull request before the change merges. That is the correct theory of the problem, and it is also the hardest kind of adoption to win, because it requires the software engineering teams who produce the data to accept a gate in their own workflow. The CLI is actively maintained, at version 0.64.3 on PyPI as of 22 July 2026. No pricing is published, so budget from a quote.

07

Confluent Schema Registry

Contract enforcement for streaming, predating the term

Worth naming because Kafka teams have been running data contracts for a decade without calling them that. A schema registry stores the schema for each topic and enforces a compatibility rule (backward, forward, full, or none) when a producer registers a new version. Break the rule and registration is rejected, which is genuine enforcement at the point of production rather than a document nobody reads. What it does not cover is everything ODCS added around the schema: no ownership, no service level, no data quality expectations beyond structure, and nothing about the warehouse tables the topic eventually lands in. If your data moves through Kafka, you already have the structural half of a contract, and the contract work left to do is the semantic half.

08

DataHub

Catalog with contracts assembled from assertions

DataHub models a data contract as an agreement bound to a single physical asset and owned by its producer, assembled from assertions you have already defined. Its documentation is explicit that a contract is verifiable against real data rather than metadata, and that freshness, schema, and data quality assertions must exist before you can attach them. That is a sound design: the contract becomes a named bundle of checks with an owner and a status, rather than a separate artifact that drifts from what is actually being tested. The practical caveat is that assertion scheduling is documented under DataHub Cloud Observe, so confirm what is available in DataHub Core for your version before assuming the whole workflow is free. DataHub Core itself is Apache 2.0 and healthy. DataHub Cloud publishes no pricing.

09

Snowflake and Databricks native constraints

Table constraints in the warehouse itself

The trap that catches teams who think they can express a contract in DDL and be done. Snowflake's own constraints documentation states that on standard tables, PRIMARY KEY, UNIQUE, and FOREIGN KEY are optional and not enforced; only NOT NULL is enforced. Hybrid tables are the exception, where primary and foreign keys are both required and enforced. Databricks behaves similarly: NOT NULL and CHECK are enforced, while primary and foreign keys are informational. So a declared primary key on a Snowflake table is documentation that the query optimizer may use, not a guarantee, and duplicate rows will land in it without complaint. Anything you need actually enforced on a warehouse table has to be checked by something outside the DDL.

10

Datatrail

Detects contract breaches and names what they break

Datatrail is not a contract authoring tool and does not try to be one. It solves the half of the problem that authoring leaves open: knowing that a contract was broken, and knowing immediately who is affected. It connects to Snowflake, BigQuery, Redshift, Databricks, or Postgres with a read-only role, builds a column-level lineage graph from query history and your dbt manifest, learns each table's normal freshness, volume, null rate, and column distributions, and alerts when any of them moves outside that baseline or when a schema changes. Because the alert arrives attached to the lineage graph, it already names the models, exposures, and dashboards reading the affected column. That is the missing piece in most contract programs: a contract states what the consumers were promised, and lineage is what tells you which consumers just stopped getting it. Use it alongside ODCS and the Data Contract CLI, not instead of them.

11

Great Expectations (GX Core)

Assertion framework, often used to back a contract

Not a contract tool, but the engine a lot of contract implementations end up sitting on, because a contract's quality section has to be executed by something. You write Expectations, group them into suites, and run them through Checkpoints against a dataframe, a file, or a warehouse table, which means the same rules can run before data lands and after. GX Core 1.20.0 was published on 7 August 2026. Two things to check before adopting: ownership split in 2026, with FICO acquiring GX Cloud and Fivetran becoming steward of the open-source GX Core, so evaluate the library rather than the hosted product, and GX 1.0 removed the profilers older tutorials still reference.

12

Atlan, Collibra and Informatica

Governance platforms adding contract features

The established governance vendors have all attached data contract features to existing catalogs, and the shape is consistent: a contract becomes another governed object alongside glossary terms, policies, and ownership, with approval workflow around it. That is genuinely valuable in an organization that already runs governance in one of these platforms, because the contract inherits the stewardship model instead of needing a new one. It is the wrong entry point if you do not, because you are buying a governance platform to get a YAML file. None of the three publishes pricing, all quote per deployment, and the third-party annual figures circulating on review and procurement sites contradict each other badly enough that some are simply wrong. We do not reprint them.

// LIMITS

The honest part

When data contracts are the wrong answer

Contracts solve a coordination problem between teams. If you do not have that problem, they add process and give you nothing back.

One team owns the whole pipeline. If the same group writes the ingestion, the models, and the dashboard, a contract is a memo you write to yourself. dbt tests and a schema check in CI give you the same protection with a fraction of the maintenance.

The producer is a vendor SaaS you do not control. You can write a contract describing what you expect from Salesforce or Stripe, and it will be a monitoring configuration with an ambitious name, because there is nobody on the other side to agree to it or to fail a build. What you actually want there is schema change alerts and freshness monitoring, so you find out the morning the vendor changed a field rather than the week after.

Nobody will own the contract. This is the failure mode that kills most programs, and it is organizational rather than technical. A contract needs a named human who will be paged, who can say no to a change, and who will still be maintaining it in a year. Write two contracts with real owners rather than forty generated ones with a distribution list in the team field.

You have four hundred tables and no idea which matter. Contracts are per-dataset and cost real effort each. Before writing any of them, find out which tables are actually read and by what, because the answer is usually a surprise and it is the only sensible way to pick the first three. That is a data lineage question, not a contract question, and it comes first.

There is also a limit worth stating plainly about what a contract can express. A contract can promise that a column is never null and that the table lands by 06:00. It cannot promise that the number is right. A checkout service can change how it calculates a discount, keep every type and every threshold intact, and produce revenue figures that are quietly wrong for a month. Contracts catch structural and statistical breaches. Semantic drift needs a human who understands the business logic, and the best any tool can do is show them what changed and what reads it.

// 5 STEPS

How to start

Rolling out data contracts without creating a YAML graveyard

01

Find what is actually read

Before writing a single contract, get the list of tables that real consumers depend on and what breaks when each one moves. Most teams discover that a third of their models have no downstream reader at all, which removes them from scope entirely.

02

Pick one painful dataset

The one that has broken across a team boundary more than once. Not the cleanest one, and not forty at once. A single contract that prevented a real incident is the only argument that wins the next twenty.

03

Generate, do not author

Run the Data Contract CLI import against the existing table to get a correct schema block, then spend your effort on the parts a machine cannot infer: the owner, the support channel, the limitations line, and the SLA.

04

Wire it into CI

Lint the contract and run its tests against a real data source on every pull request that touches the producing code. A contract that cannot fail a build is documentation, and documentation drifts within a quarter.

05

Monitor everything else

You will not write contracts for the long tail and you should not try. Cover the rest with baseline monitoring joined to lineage, so an unexpected break still names the dashboards it affects.

// HONEST

Where we fit

What Datatrail does about data contracts, and what it does not

We do not author contracts, we do not store them, and we have no opinion about your YAML. Use ODCS and the Data Contract CLI for that, both of which are free and better at it than a product feature would be.

What Datatrail covers is the two things a contract cannot do for itself. The first is deciding which datasets deserve a contract, which is a question about who reads what. Datatrail connects to Snowflake, BigQuery, Redshift, Databricks, or Postgres with a read-only role and builds a column-level lineage graph from query history and your dbt manifest, so the list of tables with real downstream consumers stops being a guess. That list is your contract backlog, in priority order, and it is usually shorter than people expect.

The second is noticing a breach on everything you never wrote a contract for. We learn each table's normal freshness, volume, null rate, and column distributions from history and alert when they move, and because the alert carries the lineage graph with it, a breach arrives already naming the models, exposures, and dashboards reading the affected column. A contract tells you what the consumers were promised. Lineage tells you which consumers just stopped getting it, which is what impact analysis exists to answer before a change ships.

Compute stays in your warehouse, no rows are copied out, and pricing is planned to be published. For the neighbouring categories, see our guides to data quality tools, data validation tools, data observability tools, data catalog tools, data profiling tools, and data governance tools.

// FAQ

Questions people ask

Data contracts, answered

What is a data contract?

A data contract is a machine-readable agreement between the team that produces a dataset and the teams that consume it, defining the schema, semantics, quality expectations, and service level of that data. It is usually a YAML file kept in version control next to the code that produces the data, which means changes to it are reviewed like code and a breaking change can fail a build. The common analogy is that a data contract does for data what an API specification does for a service.

What is the Open Data Contract Standard?

The Open Data Contract Standard, usually shortened to ODCS, is the open YAML specification for data contracts maintained under the LF AI and Data Foundation as part of the Bitol project. Version 3.1.0 was released on 8 December 2025 under Apache 2.0. It defines eleven top-level areas including fundamentals, schema, data quality, service-level agreement, team, roles, and servers. As of that release it is the de facto single industry standard, because the competing Data Contract Specification deprecated itself in favour of it.

What does a data contract look like?

It is a YAML file, usually between thirty and a hundred lines for a real table. The top declares the contract version, the dataset name, its owner, and its status. A schema block lists every column with its logical and physical type and flags the required ones. A quality block declares the rules that must hold, such as a null threshold or a freshness window. Optional blocks cover the service level, the support channel, and the team. Our worked example below is a complete ODCS contract for an orders table.

What is the difference between a data contract and a schema?

A schema describes structure: column names and types. A data contract wraps that schema in everything a consumer actually needs to depend on it, which is ownership, semantics, quality guarantees, a service level, a support channel, and a versioning policy. The distinction matters because most production incidents are not schema breaks. A column that keeps its name and type but starts arriving twelve hours late, or silently switches units, passes every schema check and breaks every dashboard.

Are data contracts worth it?

They pay off when data crosses a team boundary and the producer has no idea who depends on them. That is the specific condition. If one team owns the pipeline end to end, a contract adds ceremony without adding information, and dbt tests will serve you better. If a software engineering team ships a schema change on Tuesday and the finance dashboard breaks on Wednesday, a contract is the artifact that makes that failure preventable rather than merely detectable.

How do you enforce a data contract?

At one of five points, and most programs use two or three. In the producer's pull request, which prevents the breakage. At produce time via a schema registry, for streaming data. In CI or the pipeline, where the Data Contract CLI, Soda, or Great Expectations can fail a build against a real data source. At dbt build time, using enforced model contracts. And continuously after the data lands, with monitoring that catches what no rule anticipated. Warehouse DDL is not a fifth option, because most constraints on cloud warehouses are informational.

What is a data SLA?

A data SLA is the part of a data contract that promises timing and availability rather than structure: how often the dataset updates, the latest time it will be ready, how long history is retained, and what availability the producer commits to. In ODCS it is a first-class section of the contract. It is the clause consumers care about most and producers write last, because freshness misses cause more visible pain than schema changes do.

What is the difference between the Open Data Contract Standard and the Data Contract Specification?

They were the two competing YAML formats, and that competition ended. The Data Contract Specification, at version 1.2.1, carries a deprecation notice in its own README stating that with the release of ODCS v3.1.0 it is deprecated "in line with our commitment to focus on a single industry standard for data contracts", calls ODCS the conceptual successor, and says support in the Data Contract CLI and Entropy Data continues only until the end of 2026. If you are starting now, start with ODCS. If you have existing contracts in the older format, the Data Contract CLI exports to ODCS.

Do data contracts replace data quality tests?

No. A contract declares what must be true; tests are one of the mechanisms that check it. In practice the quality section of a contract is executed by a test engine such as the Data Contract CLI, Soda, or Great Expectations, so adopting contracts usually means keeping the tests you have and moving the declaration of them into a versioned, owned artifact. What contracts add is the ownership, the service level, and the review gate, none of which a test suite provides.

How do you start with data contracts?

Pick the one dataset that has broken most often across a team boundary and write a contract for only that. Generate a first draft with the Data Contract CLI import command against the existing table rather than starting from an empty file, fill in the owner and the support channel, and add three quality rules rather than thirty. Wire the lint and test commands into CI so a breaking change fails. Then stop and let it run for a month before expanding, because the failure mode of contract programs is a hundred unowned YAML files, not too few.

Know which datasets need a contract, and who a breach affects

Connect your warehouse read-only and get column-level lineage plus continuous checks on freshness, volume, and schema, so every breach names the models and dashboards downstream of it. Planned published pricing, no sales call.