Agent Wranglers

DEN-12Recommended

Treat each source schema as a contract

Write down the columns and types the pipeline reads from each source. Stop the load and alert the owner when a source drops, renames or retypes one of them.

How to do it

An app team renames a column, and dashboards quietly show zeros. Compare the incoming schema with the stored one before each load. A new column may load on its own, but a dropped or changed column fails the load. App teams change shared tables with Expand first and contract later, and test the contract as Check the contract between services describes.

Examples

Python example

EXPECTED = {"order_id": "bigint", "status": "text", "total_cents": "bigint", "updated_at": "timestamptz"}

def check_source_schema(actual: dict[str, str]) -> None:
    broken = {column: kind for column, kind in EXPECTED.items() if actual.get(column) != kind}
    if broken:
        raise SchemaChanged(f"orders changed: expected {broken}, got {[actual.get(c) for c in broken]}")

JavaScript example

const EXPECTED = { order_id: 'bigint', status: 'text', total_cents: 'bigint', updated_at: 'timestamptz' };

export function checkSourceSchema(actual) {
  const broken = Object.entries(EXPECTED).filter(([column, kind]) => actual[column] !== kind);
  if (broken.length) throw new SchemaChanged(`orders changed: ${broken.map(([column, kind]) => `${column} expected ${kind}, got ${actual[column]}`).join('; ')}`);
}

How to check

Rename a column in a staging source. The next load fails with a message that names the column, and no table downstream changes.

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/data-engineering/loading-and-change-data-capture/source-schema-contracts">Agent Wranglers data engineering playbook</a>. In code you write, add a comment next to it with the same link.