Datanest Digital — datanest.dev
This guide walks you through deploying the Data Contract Framework in your
Databricks environment. By the end, you will have:
main.data_governance)CREATE SCHEMA IF NOT EXISTS main.data_governance
COMMENT 'Data contract registry, SLA monitoring, and compliance metrics.';Upload registry/contract_registry.py to your Databricks workspace, then run:
from contract_registry import ContractRegistry
registry = ContractRegistry(catalog="main", schema="data_governance")
registry.initialize()This creates the contract_registry Delta table with change data feed enabled.
Pick 3-5 critical datasets to contract first. Prioritize:
Use the CLI generator to bootstrap contracts from live tables:
python cli/contract_generator.py \
--catalog main \
--schema production \
--table customer_events \
--output ./contracts/ \
--domain analytics \
--team data-engineering \
--contact data-eng@company.comTo generate contracts for all tables in a schema:
python cli/contract_generator.py \
--catalog main \
--schema production \
--all \
--output ./contracts/Each generated contract is a starting point. Review and customize:
1. Status: Change from draft to active once reviewed.
2. SLA thresholds: Set realistic freshness, completeness, and accuracy targets.
3. Constraints: Add field-level validation rules (patterns, allowed values, ranges).
4. Quality rules: Define custom SQL expressions for business logic validation.
5. PII flags: Mark fields containing personally identifiable information.
6. Lineage: Add upstream sources and downstream consumers.
Refer to spec/contract_schema.yaml for the full specification of available fields.
For new data sources, start from one of the provided templates:
| Source Type | Template |
|---|---|
| REST API / Webhook | templates/contract_templates/api_source.yaml |
| Database CDC / Batch | templates/contract_templates/database_source.yaml |
| File (CSV, JSON, etc.) | templates/contract_templates/file_source.yaml |
Copy the template, replace all values, and add domain-specific fields.
registry.register("./contracts/customer_events.yaml", registered_by="data-eng-lead")
registry.activate("customer_events", "1.0.0")Run the validator against live tables:
python cli/contract_validator.py \
--contract ./contracts/customer_events.yaml \
--source main.production.customer_eventsFor CI/CD integration, use --strict to fail on warnings:
python cli/contract_validator.py \
--contract ./contracts/customer_events.yaml \
--source main.production.customer_events \
--strict \
--output ./reports/customer_events_validation.txt1. Upload notebooks/sla_monitoring.py to your Databricks workspace.
2. Upload all active contract YAML files to a Volumes path:
/Volumes/main/contracts/active/
customer_events.yaml
financial_transactions.yaml
product_catalog.yaml
3. Create a scheduled Databricks job:
sla_monitoring.pycontract_path: /Volumes/main/contracts/activecatalog: mainschema: data_governancealert_on_breach: true (for production)Set up notifications on the SLA monitoring job:
Integrate the breaking change detector into your pull request workflow:
1. Store contracts in your Git repository under contracts/.
2. Add a CI step that compares the proposed contract against the current baseline:
# .github/workflows/contract-check.yml (GitHub Actions example)
name: Contract Change Check
on:
pull_request:
paths:
- 'contracts/**'
jobs:
check-breaking-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed contracts
id: changes
run: |
echo "files=$(git diff --name-only origin/main -- contracts/)" >> $GITHUB_OUTPUT
- name: Run breaking change detector
if: steps.changes.outputs.files != ''
run: |
# For each changed contract, compare against main branch version
for file in ${{ steps.changes.outputs.files }}; do
git show origin/main:$file > /tmp/baseline.yaml 2>/dev/null || continue
python notebooks/breaking_change_detector.py \
--baseline /tmp/baseline.yaml \
--proposed $file \
--fail-on-breaking
doneAdd a post-merge step to automatically register updated contracts:
# In your CI/CD pipeline after merge to main:
from contract_registry import ContractRegistry
registry = ContractRegistry(catalog="main", schema="data_governance")
for contract_file in changed_files:
registry.register(contract_file, registered_by="ci-pipeline")1. Upload notebooks/contract_compliance_dashboard.py to your workspace.
2. Create a scheduled job running daily:
catalog: mainschema: data_governancelookback_days: 303. Connect your BI tool (Databricks SQL, Power BI, Tableau) to the dashboard tables:
dashboard_overall_compliancedashboard_compliance_by_contractdashboard_compliance_by_check_typedashboard_daily_compliance_trenddashboard_breach_summarydashboard_freshness_distributionFor each critical data contract, formalize the relationship:
1. Copy templates/producer_consumer_agreement.md.
2. Fill in all sections with both producer and consumer teams.
3. Review and sign off.
4. Store alongside the contract YAML in version control.
Expand coverage incrementally:
Follow semantic versioning for all contracts:
| Change Type | Version Bump | Example |
|---|---|---|
| Breaking schema change | Major | 1.2.0 -> 2.0.0 |
| New optional field, relaxed constraint | Minor | 1.2.0 -> 1.3.0 |
| Documentation, description update | Patch | 1.2.0 -> 1.2.1 |
your-repo/
contracts/
active/
customer_events.yaml
financial_transactions.yaml
product_catalog.yaml
deprecated/
legacy_events_v1.yaml
drafts/
new_feature_events.yaml
agreements/
customer_events_agreement.md
.github/
workflows/
contract-check.yml
Run the generator inside a Databricks notebook or ensure your local environment
has PySpark configured. Alternatively, export table metadata as JSON and use
the --from-json flag.
Verify that the contract_path widget points to a valid Volumes or DBFS path
containing .yaml files. Check file permissions in Unity Catalog.
Ensure you are comparing the correct baseline version. The detector compares
the exact files provided — it does not resolve versions from the registry
automatically. Use git show origin/main: to get the current production
baseline.
Run registry.initialize() to create the table. This is idempotent and safe
to run multiple times.
For questions about this framework, visit datanest.dev.
*Datanest Digital — Production-ready data engineering tools.*