-
Notifications
You must be signed in to change notification settings - Fork 4
data contracts
Data contracts shift the data quality paradigm from reactive to proactive. By
specifying up front what the data will look like (schema, types, and so on), how
often it will be updated, and what quality standards it must meet, you prevent
breaking changes and unexpected surprises downstream. As a result, consumers can
build with confidence that the data will conform to the contract. And if the
producer needs to change something, they must version the contract or negotiate
updates, rather than simply pushing a change that could break dashboards or
models without warning.
Some core elements typically covered in a data contract include the following:
Schema definition
The exact structure of the data, for example, field names, data types,
acceptable values or ranges, primary keys, and relationships. This might be
expressed in a formal schema format (JSON Schema, Avro, protocol buffers,
and so forth) to allow automatic validation.
Data format and storage details
The data format of the data (JSON, CSV, Parquet, and others), character
encodings (like UTF-8), file naming conventions or table naming, and
partitioning strategy if applicable. This formatting ensures producers and
consumers are literally speaking the same language about data and
storage.
Data quality expectations
The expected levels of accuracy, completeness, and consistency, for
example, which fields can/cannot be null, valid ranges or enumerations for
values, uniqueness constraints, or other business rules the data is expected
to satisfy. These expectations often tie into automated validation checks (if
a producer’s output violates a rule, the contract can catch it).
Timeliness and SLAs
When and how often data will be delivered or updated (e.g., “by 8 a.m.
daily” or “within 15 minutes of source capture”). This sets expectations on
freshness similar to SLAs we discussed but as part of the formal contract.
Security and privacy requirements
How sensitive data is handled. For example, if certain fields contain
Personally Identifiable Information (PII), the contract might require
encryption at rest or mandate that data be masked or hashed for
consumers. It can also define access controls (who is allowed to see this
data) and compliance measures (GDPR, HIPAA, and others, if relevant).
Ownership and stewardship
Who is responsible for this data product on the producer side and perhaps
a point of contact on the consumer side. Clear ownership means any issues
with the data have a defined go-to person or team.
Lifecycle and evolution
How changes to the data contract are managed (versioning). For instance, if
a new column is added or a column’s meaning changes, the contract might
stipulate that the new version will be published while the old version is
maintained for X weeks to give consumers time to migrate. In production
environments, updates to an active contract should also include formal
communication and acknowledgment from downstream consumers.
Tooling can validate structural changes, but it cannot automatically
confirm that every dependent system has adapted safely. Requiring explicit
notification and alignment helps prevent unexpected SLA breaches or data
quality issues during contract evolution.
By formalizing these details, data contracts provide a host of benefits. They prevent
accidental breaking changes since a producer cannot just drop a column or change
its type without updating the contract and informing consumers. They ensure a high
level of data reliability and consistency, since both sides agree on what “good data”
looks like. This simplifies data integration by reducing the need for constant ad-hoc
communication between teams about schema and data meaning; much of that is
codified in the contract.
Data contracts also improve compliance with regulations and internal policies, since
requirements around privacy and governance are explicitly documented, promoting
smoother collaboration across distributed teams, because the contract serves as a
clear reference point for what is expected from each side.
Perhaps most importantly, data contracts fundamentally move data quality
processes to shift-left, meaning issues are caught at the source or early in the
pipeline rather than by downstream consumers. Instead of data engineering teams
or analysts discovering that a source system changed a field and now dashboards
are broken (a reactive scenario), the contract approach means the producer
validates and communicates changes up front. This proactive behavior significantly
reduces the fire-fighting mode that many teams find themselves in due to
unforeseen data issues.
Managing data contracts with versioning allows controlled evolution. Just like an
API, a data contract might need to change as business needs change; with version
control, a new version of the contract can be introduced while the old version is
still honored for a deprecation period. This way, downstream processes don’t break
overnight. Tooling is emerging around data contracts (for example, contracts
defined in code or YAML that can be checked into Git and validated in CI/CD
pipelines).
data_contract:
name: customer_orders_contract_v1
description: >
Defines the schema, quality, and delivery expectations for customer
orders data produced by the transactional system and consumed by the
analytics platform.
version: 1.0
producer: "ecommerce_app.orders_service"
consumer: "analytics_team.orders_pipeline"
schema:
table: orders
primary_key: order_id
fields:
- name: order_id
type: STRING
constraints: [NOT NULL, UNIQUE]
- name: customer_id
type: STRING
constraints: [NOT NULL]
- name: order_date
type: TIMESTAMP
constraints: [NOT NULL]
- name: status
type: STRING
allowed_values: ["pending", "paid", "shipped", "canceled"]
- name: total_amount
type: DECIMAL(12,2)
constraints: [NOT NULL, ">=0"]
data_quality:
expectations:
- no_nulls: [order_id, customer_id, order_date, total_amount]
- valid_enum: {status: ["pending", "paid", "shipped", "canceled"]}
- currency: "total_amount must be >= 0"
monitoring:
freshness_sla: "Data available by 06:00 UTC daily"
completeness: "At least 99.5% of transactions per day must be present"
delivery:
cadence: "daily batch, delivered by 06:00 UTC"
storage_format: "Parquet"
location: "s3://analytics-raw/orders/"
partitioning: "by order_date (daily)"
security_and_governance:
pii_fields: [customer_id]
handling:
customer_id: "must be hashed in downstream gold models"
access_control:
roles:
- name: analytics_read
permissions: ["SELECT"]
- name: finance_reporting
permissions: ["SELECT", "EXPORT"]
lifecycle:
contract_valid_from: "2025-07-25"
versioning_policy: >
Minor changes (e.g. adding nullable columns) allowed with notification.
Breaking changes require new contract version.
deprecation_policy: "Deprecated versions supported for 90 days."
Test