{
    "slug": "strangler_fig",
    "term": "Strangler Fig Pattern",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "Incrementally replace a legacy system by routing new requests to a new implementation while the old system handles the rest.",
    "long": "The Strangler Fig pattern (Martin Fowler, named after the plant that slowly replaces its host tree) migrates a legacy system by building new functionality alongside it and gradually routing traffic to the new system. A routing layer (facade) intercepts requests and directs them to old or new code based on what's been migrated. Over time, the legacy system shrinks as the new one grows, until the old system can be safely decommissioned. This avoids the risk and disruption of a big-bang rewrite.",
    "aliases": [
        "strangler fig pattern",
        "strangler pattern",
        "incremental migration"
    ],
    "tags": [
        "architecture",
        "refactoring",
        "migration",
        "design-pattern"
    ],
    "misconception": "The strangler fig pattern requires a big-bang cutover at the end. The pattern specifically avoids big-bang cutovers — traffic is gradually shifted to the new system route by route until the legacy system handles nothing and can be deleted.",
    "why_it_matters": "The Strangler Fig pattern replaces a legacy system incrementally by routing new traffic to new code while old code handles what hasn't been migrated — zero big-bang rewrites, continuous delivery throughout.",
    "common_mistakes": [
        "Not defining a proxy/facade layer to route between old and new — migrations happen directly in the old codebase.",
        "Migrating too many components simultaneously — the pattern works because it is incremental.",
        "Not deleting old code after migration — the legacy system remains and accumulates debt alongside the new.",
        "Applying the pattern to entirely greenfield development — it is a migration strategy, not an architecture."
    ],
    "when_to_use": [
        "Large legacy rewrites where replacing everything at once carries too much risk.",
        "Systems that must remain live during migration — zero-downtime replacement.",
        "When individual bounded contexts or features can be extracted and rerouted incrementally.",
        "Teams that want to validate the new system on real traffic before full cutover."
    ],
    "avoid_when": [
        "The legacy system is too tightly coupled to allow incremental routing — full rewrite may be unavoidable.",
        "The team lacks the discipline to maintain both systems — the old system rarely gets retired in practice.",
        "Short-lived projects where the migration will outlast the business need.",
        "Systems where traffic cannot be routed at the boundary — embedded or monolithic deployments with no HTTP layer."
    ],
    "related": [
        "refactoring",
        "technical_debt",
        "continuous_deployment"
    ],
    "prerequisites": [
        "microservices",
        "api_versioning",
        "feature_flag"
    ],
    "refs": [
        "https://martinfowler.com/bliki/StranglerFigApplication.html"
    ],
    "bad_code": "// Big-bang rewrite instead of incremental strangling:\n// Day 1: Stop all development on legacy app\n// Week 12: Rewrite complete (it never is)\n// Week 16: Still debugging, users still on legacy\n// Strangler fig: route /new-feature to new app, /legacy-feature to old — migrate gradually",
    "good_code": "// Gradually replace legacy by routing traffic to new implementation\nclass OrderController {\n    public function store(Request \\$req): Response {\n        if (\\$this->flags->isEnabled('new_order_service')) {\n            return \\$this->newOrderService->place(\\$req->validated());\n        }\n        return \\$this->legacyOrderProcessor->process(\\$req->all());\n    }\n}\n\n// Increase rollout: 5% → 25% → 50% → 100%\n// At 100% and stable, delete the legacy path",
    "example_note": "The strangler fig grows around the old tree until the old tree is gone — applied to software, new code wraps old code and gradually replaces it.",
    "quick_fix": "Route a portion of traffic to the new implementation behind a feature flag; gradually shift traffic as confidence grows; decommission the old code when at 100%",
    "severity": "info",
    "effort": "high",
    "created": "2026-03-15",
    "updated": "2026-03-25",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/strangler_fig",
        "html_url": "https://codeclaritylab.com/glossary/strangler_fig",
        "json_url": "https://codeclaritylab.com/glossary/strangler_fig.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Strangler Fig Pattern](https://codeclaritylab.com/glossary/strangler_fig) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/strangler_fig"
            }
        }
    }
}