{
  "docVersion": 1,
  "id": "template-strangler-fig-migration",
  "name": "Strangler-fig migration",
  "purpose": "Incremental monolith escape: a routing facade shifts traffic per route to a new service, an anti-corruption layer translates legacy data, and backfill-then-cutover with dark reads makes the switch provable instead of hopeful.",
  "nodes": {
    "users": {
      "type": "users",
      "label": "Traffic",
      "x": 20,
      "y": 260,
      "runtime": "unchanged clients"
    },
    "facade": {
      "type": "gateway",
      "label": "Routing facade",
      "x": 270,
      "y": 260,
      "runtime": "per-route: 80% old · 20% new",
      "color": "blue",
      "notes": "The strangler itself. Every migrated route is one config change here — and one config change back if it goes wrong."
    },
    "mono": {
      "type": "monolith",
      "label": "Legacy monolith",
      "x": 560,
      "y": 90,
      "runtime": "shrinking · frozen features",
      "color": "gray"
    },
    "olddb": {
      "type": "database",
      "label": "Legacy DB",
      "x": 1060,
      "y": 90,
      "runtime": "still authoritative (for now)",
      "color": "gray"
    },
    "acl": {
      "type": "server",
      "label": "Anti-corruption layer",
      "x": 810,
      "y": 260,
      "runtime": "legacy model → clean model",
      "color": "purple",
      "notes": "The new service never speaks legacy: this translator absorbs the old schema's quirks so they can't leak into the new domain model."
    },
    "newsvc": {
      "type": "k8s",
      "label": "New Orders service",
      "x": 560,
      "y": 430,
      "runtime": "clean domain · new stack",
      "color": "green",
      "patterns": [
        "canary",
        "stateless"
      ]
    },
    "backfill": {
      "type": "batch",
      "label": "Backfill + verify",
      "x": 1060,
      "y": 260,
      "runtime": "copy history · diff · report",
      "notes": "Copies legacy rows into the new store and verifies checksums. Cutover happens only when the diff report reads zero."
    },
    "newdb": {
      "type": "database",
      "label": "New DB",
      "x": 1060,
      "y": 430,
      "runtime": "authoritative after cutover",
      "color": "green"
    }
  },
  "edges": {
    "e1": {
      "from": "users",
      "to": "facade",
      "fromSide": "right",
      "toSide": "left",
      "label": "100% of traffic",
      "animated": true
    },
    "e2": {
      "from": "facade",
      "to": "mono",
      "fromSide": "right",
      "toSide": "left",
      "label": "unmigrated routes"
    },
    "e3": {
      "from": "facade",
      "to": "newsvc",
      "fromSide": "right",
      "toSide": "left",
      "label": "orders routes · 20% and rising",
      "animated": true,
      "color": "green"
    },
    "e4": {
      "from": "mono",
      "to": "olddb",
      "fromSide": "right",
      "toSide": "left"
    },
    "e5": {
      "from": "newsvc",
      "to": "newdb",
      "fromSide": "right",
      "toSide": "left"
    },
    "e6": {
      "from": "newsvc",
      "to": "acl",
      "fromSide": "top",
      "toSide": "bottom",
      "label": "needs legacy customer data"
    },
    "e7": {
      "from": "acl",
      "to": "mono",
      "fromSide": "left",
      "toSide": "right",
      "label": "translated legacy calls"
    },
    "e8": {
      "from": "olddb",
      "to": "backfill",
      "fromSide": "bottom",
      "toSide": "top",
      "label": "copy history",
      "style": "dashed"
    },
    "e9": {
      "from": "backfill",
      "to": "newdb",
      "fromSide": "bottom",
      "toSide": "top",
      "label": "verified rows",
      "style": "dashed"
    }
  },
  "boxes": {
    "b1": {
      "x": 530,
      "y": 30,
      "w": 720,
      "h": 200,
      "label": "the old world — being strangled",
      "color": "gray",
      "opacity": 0.04
    },
    "b2": {
      "x": 530,
      "y": 370,
      "w": 720,
      "h": 200,
      "label": "the new world — earning trust route by route",
      "color": "green",
      "opacity": 0.04
    }
  },
  "texts": {
    "t1": {
      "x": 20,
      "y": 440,
      "text": "dark reads: for migrated routes the facade can query\nBOTH sides, serve the old answer, and log any diff.\nCutover happens when the diff rate is zero for a week —\nconfidence measured, not assumed.",
      "color": "purple",
      "size": 12
    }
  },
  "meta": {
    "createdAt": "2026-07-13T09:00:00.000Z",
    "modifiedAt": "2026-07-13T09:00:00.000Z"
  }
}