How your generated code can carry its own lineage, dependencies, and release identity.
The Problem We Keep Re-Inventing
Every generated artifact — a SQL table, view, UDF, or mapping script — has a story behind it.
🔹Which model version was used?
🔹Which upstream tables feed it?
🔹Which dashboards depend on it?
🔹When was it last generated, by whom, and for which release?That information exists in our metadata repository, notebooks, or CI logs.
But once the code lands in the data warehouse, all context disappears.
🔹What remains is a naked object — executable but context-less.
🔹When someone asks “why does this table exist?” the answer lives somewhere else.
So here’s a radical but simple idea:
Let every generated artifact carry its own metadata — right inside its comment header.
Not a human summary, but a machine-readable metadata block.
One that fully describes the object, its lineage, dependencies, business meaning, and integrity.

The Inspiration: Front-Matter
Static-site builders like Jekyll, Hugo, or MkDocs have long solved this.
Each Markdown page starts with a YAML front-matter block, wrapped between --- lines:
title: “Embedding Metadata in SQL”
author: “Jaco van der Laan”
tags: [metadata, sql, automation]
date: 2025-11-02
That little block tells the system how to interpret the file — metadata and content living together in one artifact.
So why not give our data models the same superpower?
From Markdown Pages to Metadata-Driven Pipelines
In a metadata-driven architecture, we already generate our SQL. That means we can inject structured metadata at generation time — no extra step needed.
Each artifact can begin with a YAML front-matter block, enclosed in SQL comments:
/—
kind: model
name: mart.orders_daily
version: 1.5.0
release: r2025.11.2
generated_at: 2025-11-02T14:22:31Z
logical_model: “Sales > Orders > Daily”
description: >
Daily order facts aggregated at (customer_id, order_day). Includes cancellations.
sources:
– raw.orders_v3
– dim.customer
depends_on:
– stg.orders_clean
– dim.customer_current
consumed_by:
direct: [dash.orders_kpi, api.orders_export]
indirect: [ml.churn_v2]
kpi:
– code: ORDERS_TOTAL
definition: “count() where status=’completed’”
owners:
business: “Sales Ops”
technical: “Data Platform”
integrity:
body_sha256: “b7c3…”
changelog:
– date: 2025-11-02
version: 1.5.0
release: r2025.11.2
change_type: feature
summary: “Added gross_amount cap for refunds”
tickets: [ADO-1234, ADO-1299]
– date: 2025-10-18
version: 1.4.2
change_type: fix
summary: “Excluded test customers from aggregates”
—*/
Followed by the actual SQL logic.
CREATE OR REPLACE TABLE mart.orders_daily AS
SELECT
c.customer_id,
o.order_day,
count(*) AS order_count,
sum(o.gross_amount) AS gross_amount
FROM stg.orders_clean o
JOIN dim.customer_current c USING (customer_id)
GROUP BY c.customer_id, o.order_day;
Why YAML?
YAML is readable, diff-friendly, and supports nested structures like dependencies or KPIs. Other options (JSON, TOML) work, but YAML hits the sweet spot between human clarity and machine precision.
By choosing a fixed delimiter (/*--- … ---*/) we make it easy to extract programmatically in any language.
What Goes Into the Header
A good metadata header should tell the entire story of the object:

This makes the object self-describing, not just executable.
The Atomic Object Concept
Think of each generated artifact as an atomic object — a self-contained unit that carries both:
- its executable body (the SQL code), and
- a metadata bag that describes everything about it.
When deployed, the object can register itself in a metadata schema — much like an organism emitting its DNA.
- The CI/CD pipeline extracts and validates the header.
- It computes a body hash (
body_sha256) to ensure integrity. - It executes the SQL.
- It upserts the metadata into your warehouse metadata tables.
- It logs the version and changelog entries for automated release note generation.
Adding Version History and Dynamic Release Notes
This is where the concept becomes even more powerful. By embedding a short changelog in each artifact — and letting your CI/CD pipeline store the full version history — your platform gains the ability to generate release notes automatically.
Each entry in the header’s changelog section documents what changed, why, when, and by whom. Those snippets can be aggregated to form a live release report — per object, per domain, or per release window.
Imagine being able to open your metadata dashboard and see:
“Release 2025.11.2–12 new features, 4 fixes, 2 breaking changes across 47 models.”
🔹All generated from the headers themselves.
🔹No manual documentation.
🔹No post-hoc detective work.
A Minimal Metadata Schema
Your metadata store can mirror this structure:
Press enter or click to view image in full size

This schema becomes your truth graph — the living record of your platform’s evolution.
Why This Matters
- Traceability: Each object carries its own lineage, ownership, and release context.
- Auditability: Every deployed object can explain its own origin.
- Automation: CI/CD pipelines can build release notes, test dashboards, or impact analyses directly from headers.
- Governance by Construction: Metadata doesn’t lag behind reality — it is reality.
- Developer Delight: Open any SQL file, and you immediately understand what it does, who owns it, and why it changed.
This transforms documentation from a manual afterthought into a self-sustaining system.
The Power of Living Metadata
When metadata lives with the code — not next to it — it becomes a dynamic force:
Generate → Deploy → Register → Discover → Regenerate.
Every artifact turns into a living node in your platform’s knowledge graph — portable, auditable, and verifiable.
Coming Next: Implementation Deep Dive
In the next article, 🧠 “From Concept to Code: Building Self-Describing SQL Objects” (coming soon), we’ll go hands-on with:
- A Python extractor and validator for YAML front-matter
- The SQL schema for your metadata tables
- A pre-commit hook to block missing or invalid headers
- CI/CD integration to auto-generate release notes
That follow-up will complete the full cycle — from inspiration to operational reality.
In Summary
