A business-critical application can be both valuable and difficult to change. It may process orders reliably every day while depending on an unsupported framework, brittle integrations, undocumented rules and releases that take weeks to coordinate. The temptation is to commission a complete replacement. That sounds clean on a roadmap but can force the business to fund two systems for a long period, delay new features and rediscover years of hidden behavior.
There is another option: replace capabilities in controlled increments while the existing application continues to serve customers. The strangler pattern is an architectural approach to doing exactly that. It is not a shortcut around testing or data migration. It is a way to make modernization a sequence of smaller, measurable business decisions instead of one high-stakes launch.
For a CEO or CTO, the key question is not whether the team can build a modern application. It is whether the organization can move essential workflows to a better architecture without losing transactions, disrupting customers or creating permanent duplication.
Executive summary: five decisions before writing replacement code
- Define the business outcome. Is the objective faster releases, reduced security exposure, easier integration, better uptime or lower operating cost? A technology refresh without a measurable outcome is difficult to govern.
- Select a bounded capability. Start with a workflow that has a clear owner, a manageable dependency footprint and enough value to justify migration.
- Decide where requests and data will go. A routing facade is useful, but a successful migration also requires explicit rules for reads, writes, identifiers and background jobs.
- Prove reversibility before cutover. A traffic switch is not a rollback plan if the new system has already written data the old system cannot interpret.
- Fund retirement, not just replacement. The business realizes long-term savings only when old endpoints, jobs, dependencies and infrastructure are actually removed.
What is the strangler pattern?
The strangler pattern, also called the strangler fig pattern, incrementally replaces an existing system with new components. Rather than launching a complete substitute on one date, teams introduce a boundary in front of the legacy system, implement a new capability behind that boundary, redirect a limited set of requests and expand the new system’s responsibility as evidence accumulates.
The metaphor comes from Martin Fowler’s explanation of the strangler fig approach. The architectural idea is more important than the name: keep the business running, create seams around existing behavior and shift responsibility one capability at a time.
A typical progression looks like this:
- Initially, all requests continue to reach the legacy application through a controlled interface.
- The team builds one replacement capability with explicit inputs, outputs and acceptance criteria.
- The interface routes eligible requests to the replacement and sends the rest to the legacy system.
- Monitoring, reconciliation and business testing determine whether the new capability is safe to expand.
- Once all dependencies are retired, the legacy implementation of that capability is removed.
A facade might be an API gateway, reverse proxy, application router or internal abstraction. It does not have to be a microservices platform. A modular monolith with clean boundaries may be the better destination for a small or mid-sized team.
When incremental modernization is worth considering
This approach is particularly useful when the current system must remain available, business rules are incompletely documented and a full replacement would take longer than the organization can wait for improvements.
Common triggers include a customer portal whose user interface is overdue for change, an order-management application that needs new integrations, a legacy application with slow deployment cycles, or a system that must expose selected capabilities to mobile apps and partners.
The strongest candidates have an identifiable seam. For example, document generation, customer notifications, catalog search or a self-contained reporting service may be easier to separate than a transaction workflow that touches dozens of shared tables.
Do not assume that old code automatically needs replacing. An application with acceptable security, performance and release reliability may benefit more from targeted refactoring, dependency upgrades or stronger tests. Actiknow’s legacy PHP modernization guide explains how to distinguish refactoring, incremental modernization, rewriting and replacement without treating age alone as a reason to rebuild.
When the strangler pattern may be the wrong choice
It can be disproportionate for a small application that is easy to replace and has few dependencies. It is difficult when requests cannot be intercepted, the application is tightly coupled to a proprietary runtime, or the business cannot tolerate a period of dual operation. If the system is being retired entirely or replaced by a standard SaaS product, a simpler migration may be preferable.
The pattern also does not resolve a compromised or unsupported component automatically. Immediate security remediation may still be necessary while the longer modernization plan proceeds.
Start with a capability map, not a list of technologies
A common planning error is to begin with a target stack: React, cloud services, containers, a message broker and a new database. That describes components but not the business functions they must preserve.
Instead, inventory capabilities and dependencies. For each workflow, record:
- Business owner and criticality, including the impact of incorrect output or downtime.
- Users and channels, including internal screens, APIs, partner systems and mobile apps.
- Input events, business rules, calculations, state transitions and approvals.
- Data entities read and written, plus system-of-record ownership.
- Integrations, scheduled jobs, files, reports and downstream consumers.
- Current incident rate, change frequency, lead time and operational cost.
- Security, privacy, audit and retention obligations.
- Test coverage and the quality of existing documentation.
Build a dependency graph rather than relying only on interviews. Review access logs, database query patterns, job schedules, source code references and outbound API calls. An endpoint that appears unused may still serve a monthly reconciliation or year-end export.

Score potential migration slices
A practical scoring model can use four dimensions: business value, independence, implementation uncertainty and rollback complexity. Rate each on a consistent scale and document the evidence behind the rating.
A strong first slice is not necessarily the most valuable feature. It is often a medium-value capability that exercises the new deployment, monitoring and routing approach without putting the company’s most sensitive transaction path at risk. Early learning has value, but only if the first migration is real enough to expose architectural weaknesses.
The target architecture: a controlled boundary around change
At a high level, clients call a stable entry point. That entry point sends each request to the legacy implementation or the new implementation. Both may temporarily depend on shared identity, data or integration services, but those dependencies should be documented and reduced over time.
The entry point must preserve authentication, authorization, tenant context, correlation IDs, request validation and error behavior. If a legacy application returns a particular status or error contract, changing it unexpectedly can break customers even when the replacement function appears correct.
The routing layer is production infrastructure. Treat it as a potential availability and latency risk, not merely a switch. Monitor routing decisions, fallback behavior, response times, error rates and the distribution of traffic between implementations.

Routing by capability is safer than routing randomly
Prefer deterministic routing based on explicit capabilities or stable customer cohorts. For example, a document-download endpoint may be routed entirely to the new implementation, while order updates remain on the old one. Alternatively, a limited set of pilot tenants may use a new workflow.
Randomly splitting stateful transactions between two implementations can create inconsistencies. If a customer starts a multi-step process in one system and completes it in another, both systems must agree on the state machine, identifiers and side effects.
Routing decisions should be versioned, auditable and reversible. Record which implementation served each request so support teams can reconstruct incidents.
External routing is not always possible
Sometimes the behavior to replace lives deep inside a monolith and cannot be intercepted at its perimeter. In that situation, introduce an internal interface and change callers to use it before swapping implementations. This is often described as branch by abstraction; AWS’s branch-by-abstraction guidance describes why it can be preferable for internal dependencies.
The important choice is the seam, not whether every change passes through an API gateway.
Data ownership is the hardest part of coexistence
Many modernization programs focus on routing screens and endpoints while leaving database ownership vague. That is dangerous because two applications can return the correct page and still corrupt business state.
For each entity, define one authoritative writer during each phase. If the legacy application owns customer balances, the replacement should not independently update a second balance table without a carefully designed consistency mechanism. Read-only replicas and projections are often easier to introduce than parallel writable stores.
A practical data-transition decision record should answer:
- Which system owns creation, updates and deletion of each entity?
- How are IDs mapped between legacy and new records?
- What is the maximum acceptable delay between systems?
- How are late events, retries, duplicates and out-of-order updates handled?
- What happens when synchronization fails?
- How are historical corrections, reversals and deletions propagated?
- How will the team reconcile both representations and prove cutover readiness?
Three workable data-transition strategies
Strategy 1: Keep the legacy database as the system of record initially. New components call governed interfaces or use carefully controlled access while the team learns the business rules. This reduces the number of simultaneous changes but may preserve old schema constraints temporarily.
Strategy 2: Move ownership for one bounded entity or capability. The team migrates its data, redirects all authoritative writes and gives legacy consumers a compatibility interface. This can create cleaner ownership but requires a detailed consumer inventory.
Strategy 3: Build read models or projections from authoritative events or change data capture. This supports new search, reporting or user experiences without immediately transferring write ownership. It introduces synchronization and replay requirements.
Dual writing to two databases from the same request should be treated as a high-risk transitional choice, not a default architecture. A network timeout can leave one write successful and the other uncertain. If dual writes cannot be avoided, design idempotency, durable recovery, reconciliation and clear ownership before production use.
Reconciliation is a release gate, not a reporting exercise
Compare more than record counts. Validate monetary totals, lifecycle states, relationships, permissions, time-zone handling, historical changes and domain-specific calculations. Track mismatches by severity and assign owners.
For transactional flows, test repeated requests, partial failures and retries. A replacement that creates duplicate invoices under retry is not ready even if its normal-path responses match the old system.
Preserve contracts for users and integrations
Legacy behavior is often the only specification available. Business users may depend on undocumented field meanings, CSV layouts, date formats, sort orders or error messages. External integrations may rely on a file appearing at a particular time.
Build characterization tests around the current behavior before changing it. Capture representative requests and expected outputs, then decide deliberately which behaviors must remain identical and which are approved improvements.
Use contract tests for APIs and file exchanges, regression tests for critical business rules, and end-to-end tests for workflows crossing both implementations. Treat authentication, authorization and audit events as part of the contract, not optional infrastructure concerns.
Where possible, mirror or replay safe, sanitized production-like traffic into the new implementation without allowing it to create real side effects. Compare outputs and latency. Avoid mirroring payment, notification or write operations unless a controlled sandbox makes duplicate effects impossible.
Rollback must include data, not just traffic
A reverse proxy can return requests to the legacy application in seconds. That is useful only if the legacy application can still understand the current state.
Consider an illustrative order workflow. The new component introduces a status called “awaiting external approval.” If it writes that status into a shared table and the old code does not recognize it, switching the route back may not restore service. The traffic rollback succeeded; the business rollback failed.
Before each cutover, write down:
- The precise conditions that trigger rollback, including error rate, latency, reconciliation differences and user-impact thresholds.
- Who can authorize rollback and who executes it.
- Whether the old implementation remains compatible with newly written data.
- How to stop background workers and queued messages safely.
- Whether in-flight transactions need draining, compensation or manual review.
- How to validate recovery and communicate incidents.
Prefer backward-compatible schema changes during transition. Introduce new fields before depending on them, avoid destructive changes until consumers have migrated, and maintain explicit compatibility windows. For irreversible changes, design a forward-fix or compensating workflow rather than promising an impossible instant rollback.
Operational safeguards during the migration
Coexistence increases moving parts. The old and new systems may have different logging, deployment pipelines, secrets, databases and on-call teams. Without shared observability, incident diagnosis becomes slower just when risk is elevated.
Establish common correlation IDs, distributed tracing where practical, consistent business event names, deployment markers and dashboards that separate legacy and replacement traffic. Monitor customer-facing outcomes, not only CPU utilization.
Minimum operational controls include:
- Error rate and latency by route, implementation, tenant and release.
- Queue backlog, dead-letter volume, retry attempts and idempotency failures.
- Data reconciliation exceptions and their age.
- Authentication failures and permission mismatches.
- Deployment frequency, failed releases and recovery time.
- A tested runbook for routing changes and production incidents.
Do not let the routing facade become a permanent, undocumented maze. Keep a routing register that states which capability is served where, the intended end state and the owner responsible for retiring transitional logic.

A concrete example: modernizing an order-management application
The following scenario is illustrative, not a client case study.
Suppose a B2B distributor uses a ten-year-old order-management application. Customers place orders through a portal; staff approve credit exceptions; warehouse teams receive pick lists; finance exports invoices; and partner systems pull order status through scheduled integrations.
A full rewrite would need to reproduce every approval rule, pricing exception and integration before launch. A phased approach could look different.
Phase A: Inventory workflows and create tests around order totals, discounts, tax, status transitions, credit approvals and invoice exports. Introduce correlation IDs and a stable routing entry point.
Phase B: Replace read-only order search and history views first. Keep order creation and updates in the legacy system. Compare search results, permissions and performance before enabling the new interface for more users.
Phase C: Move notification delivery behind a stable interface. The new component handles templates and delivery retries while the legacy application remains the source of business events. Verify that duplicate events do not send duplicate customer messages.
Phase D: Extract a bounded order capability only after ownership of the relevant data and integrations is understood. Route one pilot cohort, reconcile transaction outcomes and maintain a proven recovery path.
Phase E: Remove old code, unused tables, scheduled tasks and routing exceptions once the migrated capability has passed business acceptance and no hidden consumers remain.
This sequence is not universal. In a system with deeply coupled order data, search might be easy while order updates are uneconomic to extract. The roadmap should follow actual dependencies, not a predetermined microservices diagram.
A 90-day pilot plan executives can govern
A pilot should produce a decision, not merely a prototype. Ninety days is a planning illustration; actual timing depends on system access, risk, testing maturity and the chosen slice.
Days 1–20: Discover and establish the baseline
Identify the business owner, map the selected capability, inventory its consumers and data dependencies, capture current performance and incident metrics, and create characterization tests. Record the cost of current change and the risks of leaving the capability untouched.
Deliverables: capability map, dependency inventory, baseline metrics, proposed boundary, security review and a decision on whether the slice is suitable.
Days 21–40: Build the seam and prove observability
Introduce the routing or abstraction boundary in a way that initially preserves legacy behavior. Instrument requests, failures and business events. Test routing failover, authentication and authorization.
Deliverables: production-safe boundary, dashboards, contract tests, runbooks and a rollback rehearsal that does not yet depend on the new capability.
Days 41–65: Implement and compare the replacement
Build the bounded capability, create migration scripts or projections if required, test edge cases and compare outputs against the legacy implementation. Review any differences with business owners.
Deliverables: working replacement, reconciliation reports, performance evidence, security test results and a documented data-ownership decision.
Days 66–90: Pilot, measure and decide
Enable the replacement for a limited, stable cohort or route. Watch technical and business metrics, exercise recovery procedures and obtain sign-off. Decide whether to expand, revise the architecture, choose a different slice or stop.
Deliverables: pilot results, exceptions, total cost of coexistence, a retirement checklist and an evidence-based next-phase recommendation.

What should the executive dashboard measure?
Do not report modernization progress as percentage of code rewritten. Code volume is a poor proxy for reduced business risk.
Track five categories:
- Business continuity: customer-impacting incidents, transaction failures, service availability and unresolved reconciliation differences.
- Delivery effectiveness: lead time for changes, deployment frequency, rollback frequency and time to restore service.
- Modernization coverage: share of real transactions served by the new capability, dependencies retired and number of legacy consumers remaining.
- Financial control: development spend, dual-run infrastructure and support costs, plus actual costs eliminated when legacy components are decommissioned.
- Business outcomes: cycle time, manual interventions, customer experience or integration speed tied to the original investment case.
Define baselines before the pilot. An increase in cloud spend during coexistence may be expected; it is not automatically a failure. But leadership should see how long dual-running is planned and what conditions unlock retirement.

Budget for the transition architecture
A phased approach spreads risk and investment, but it is not free. Costs can include discovery, characterization tests, facade development, duplicated infrastructure, data synchronization, observability, reconciliation, training and the effort of supporting two implementations.
A useful investment model separates three categories: work that produces lasting capability, temporary coexistence cost and retirement savings. Temporary components should have explicit owners and removal dates.
For an illustrative planning exercise, suppose a pilot costs $80,000 and dual operations add $2,000 per month for six months. The transition commitment is $92,000 before contingency and ongoing support. Those figures are hypothetical, not market benchmarks. The decision should compare that commitment with the expected reduction in incidents, release effort or business delays, using the organization’s own baseline.
Beware of the program that successfully creates new services but never switches off old ones. It can increase total operating cost and security exposure indefinitely.
Governance: who owns the decision?
The CTO or engineering leader owns architecture, delivery risk and operational readiness. The business capability owner defines correct behavior and signs off on customer impact. Security and data owners approve relevant controls. Finance tracks total investment and retirement benefits.
Create a short decision record for every migrated capability: why it is being moved, what is in scope, who owns data, what success looks like, what can fail, how to reverse the cutover and what must be removed afterward.
For teams seeking delivery support, Actiknow’s custom web application development practice describes assessment, migration, integration, testing, deployment and ongoing support. Its custom solutions and integration services cover applications, APIs, databases and automation that may be relevant to a phased program. The right scope should follow an assessment of the actual legacy system rather than a generic architecture package.
Common mistakes that make incremental modernization unsafe
Building a new interface over the same undocumented coupling
A modern frontend does not solve the problem if it calls a tangled set of legacy tables and stored procedures directly. Introduce contracts and ownership rather than moving the coupling to a different location.
Splitting services before splitting responsibilities
Microservices create independent deployment and operational responsibilities. If one team owns all components and every change still requires coordinated releases, a modular monolith may be simpler.
Treating all legacy behavior as correct
Characterization tests reveal existing behavior; business owners must decide which behaviors are requirements and which are defects or obsolete workarounds.
Ignoring jobs, reports and integration consumers
A capability is not retired merely because the user interface moved. Scheduled exports, audit reports and third-party consumers may still depend on it.
Assuming a feature flag solves rollback
Flags can reverse routing, but not necessarily schema changes, financial postings, notifications or messages already delivered. Recovery needs a data and side-effect plan.
Failing to decommission
If the old endpoint, credentials, jobs and infrastructure remain live indefinitely, the business inherits two attack surfaces and two support burdens. Retirement criteria belong in the original project scope.
Frequently asked questions
Is the strangler pattern the same as a microservices migration?
No. It is an incremental replacement strategy. The destination might be microservices, a modular monolith, managed services or a combination. Service granularity should follow team capacity, business boundaries and operational requirements.
Can we use it when the legacy application has no APIs?
Sometimes. A proxy may intercept existing HTTP requests, or the team can add an internal abstraction. For batch and desktop systems, adapters or controlled data interfaces may be needed. If no safe interception seam exists, another migration strategy may be more appropriate.
Do we need to move the database first?
Usually not. Moving code and data simultaneously can increase risk. Keeping a single authoritative writer while introducing new read models or bounded capabilities is often safer. Data ownership must be designed explicitly.
How do we avoid losing transactions during cutover?
Use deterministic routing, idempotency keys, durable event handling where appropriate, transaction reconciliation, compatibility testing and controlled draining of in-flight work. Test failure cases rather than relying only on normal-path demonstrations.
How long does a strangler modernization take?
There is no credible universal duration. A small isolated capability might be delivered in weeks; a tightly coupled enterprise workflow can take months or longer. Estimate each slice after dependency discovery and include coexistence and retirement work.
What should we modernize first?
Choose a capability with measurable value, clear boundaries, limited data ownership ambiguity and a feasible recovery path. Avoid selecting the most business-critical workflow merely because it has the highest visibility.
When is a full rewrite better?
A full rewrite can make sense when the product is fundamentally changing, the existing system is small enough to replace safely, or incremental seams would be more expensive and risky than a controlled replacement. It still requires data migration, parity testing and cutover planning.
How do we know when the old system can be shut down?
Require evidence that all intended traffic and jobs have moved, hidden consumers have been identified, reconciliation exceptions are resolved, retention obligations are met, support runbooks are updated and business owners have accepted the new capability.
Conclusion: modernize at the speed of evidence
The strangler pattern works when modernization is treated as a controlled transfer of responsibility. The objective is not to celebrate new services or a cleaner architecture diagram. It is to improve a business-critical system while preserving the transactions, integrations and decisions that depend on it.
Start with a capability map. Make data ownership explicit. Establish observable routing and tested recovery. Deliver one bounded slice, measure the outcome and retire the old implementation deliberately. Each successful migration should make the next one less uncertain.
If your organization is weighing a legacy application rewrite against phased modernization, contact Actiknow to discuss a focused application and integration assessment. The useful first deliverable is a realistic boundary, risk and migration plan, not a commitment to rebuild everything.

