{
  "docVersion": 1,
  "id": "template-cdc-replication-backbone",
  "name": "CDC backbone",
  "purpose": "Debezium-style connector tails the OLTP WAL; row changes and outbox events flow through a schema-checked stream to search, cache invalidation and the warehouse.",
  "nodes": {
    "app": {
      "type": "k8s",
      "label": "Order Service",
      "x": 0,
      "y": 240,
      "runtime": "writes rows + outbox",
      "patterns": [
        "stateless"
      ]
    },
    "db": {
      "type": "database",
      "label": "OLTP Postgres",
      "x": 260,
      "y": 240,
      "runtime": "WAL = changelog",
      "color": "blue",
      "patterns": [
        "backup"
      ],
      "notes": "The WAL already records every committed change in order — CDC turns it into a public stream."
    },
    "cdc": {
      "type": "worker",
      "label": "CDC Connector",
      "x": 520,
      "y": 240,
      "runtime": "tails WAL · logical decoding",
      "color": "purple",
      "notes": "Emits one event per row change with before/after images. Restart-safe: resumes from the last LSN."
    },
    "reg": {
      "type": "registry",
      "label": "Schema Registry",
      "x": 520,
      "y": 20,
      "runtime": "compatibility gate"
    },
    "log": {
      "type": "stream",
      "label": "Change Stream",
      "x": 780,
      "y": 240,
      "runtime": "per-table topics · keyed by PK",
      "patterns": [
        "sharded"
      ]
    },
    "idx": {
      "type": "search",
      "label": "Search Index",
      "x": 1040,
      "y": 60,
      "runtime": "rebuilt from stream"
    },
    "cache": {
      "type": "cache",
      "label": "Cache Invalidation",
      "x": 1040,
      "y": 240,
      "runtime": "evict on change"
    },
    "wh": {
      "type": "etl",
      "label": "Streaming ETL → Warehouse",
      "x": 1040,
      "y": 420,
      "w": 190,
      "runtime": "transform in-flight"
    },
    "dlq": {
      "type": "dlq",
      "label": "Dead Letters",
      "x": 780,
      "y": 470,
      "runtime": "unparseable changes",
      "color": "amber"
    }
  },
  "edges": {
    "e1": {
      "from": "app",
      "to": "db",
      "fromSide": "right",
      "toSide": "left",
      "label": "txn: rows + outbox",
      "animated": true
    },
    "e2": {
      "from": "db",
      "to": "cdc",
      "fromSide": "right",
      "toSide": "left",
      "label": "WAL",
      "animated": true,
      "patterns": [
        "ordered"
      ]
    },
    "e3": {
      "from": "cdc",
      "to": "reg",
      "fromSide": "top",
      "toSide": "bottom",
      "label": "check schema",
      "patterns": [
        "authenticated"
      ]
    },
    "e4": {
      "from": "cdc",
      "to": "log",
      "fromSide": "right",
      "toSide": "left",
      "label": "change events",
      "animated": true
    },
    "e5": {
      "from": "log",
      "to": "idx",
      "fromSide": "right",
      "toSide": "left",
      "label": "upsert docs",
      "style": "dashed",
      "patterns": [
        "idempotent"
      ]
    },
    "e6": {
      "from": "log",
      "to": "cache",
      "fromSide": "right",
      "toSide": "left",
      "label": "evict keys",
      "style": "dashed"
    },
    "e7": {
      "from": "log",
      "to": "wh",
      "fromSide": "right",
      "toSide": "left",
      "label": "append facts",
      "style": "dashed",
      "patterns": [
        "batch"
      ]
    },
    "e8": {
      "from": "log",
      "to": "dlq",
      "fromSide": "bottom",
      "toSide": "top",
      "label": "poison",
      "style": "dashed"
    }
  },
  "boxes": {
    "b1": {
      "x": 1000,
      "y": -40,
      "w": 280,
      "h": 620,
      "label": "derived views — all rebuildable",
      "color": "green",
      "opacity": 0.04
    }
  },
  "texts": {
    "t1": {
      "x": 0,
      "y": 440,
      "text": "why CDC beats dual-writes: the app writes ONCE\n(its own database). everything downstream derives\nfrom the WAL — which can't disagree with the data,\nbecause it IS the data.",
      "color": "green",
      "size": 12
    }
  },
  "meta": {
    "createdAt": "2026-07-13T09:00:00.000Z",
    "modifiedAt": "2026-07-13T09:00:00.000Z"
  }
}