About Us AI
Industries
Platforms
Services
Our Work Blog Contact
EnglishDeutsch
Get a Quote
Laravel

Strangler Fig: Migrating a Legacy PHP Monolith to Laravel Without a Feature Freeze

The big-bang rewrite is the most reliably catastrophic project in software, and everyone knows it, and companies keep commissioning it. The alternative is less dramatic and it works: replace the old system one route at a time while it keeps running.

Migrating a legacy PHP monolith to Laravel using the strangler-fig pattern

Every legacy PHP application reaches the same meeting. The codebase is a decade old, nobody wants to touch the order module, the framework it uses has not had a release since 2019, and someone proposes a rewrite. Eighteen months, they say. Feature freeze while we do it.

That project has a well-documented failure rate, and the mechanism is always identical: the business cannot actually stop for eighteen months, so changes get made to the old system, the new one falls behind, and the migration becomes a permanently moving target. Two years later you have two systems and one is unfinished.

The strangler fig pattern avoids that by never having a cutover. New functionality is built in Laravel, existing functionality is moved across route by route, and traffic is directed to whichever system currently owns each path. The old application shrinks until it is gone.

Version context: Laravel 13 shipped in March 2026 with no breaking changes from 12 and a PHP 8.3 floor. For a migration project that matters — the framework you are moving to is unusually stable right now, and the PHP version requirement is often the real gate.

The Routing Boundary

Everything depends on being able to send a request to either application without the user knowing. Put a reverse proxy in front of both and route on path.

  • Default everything to the legacy application on day one, so the proxy is a no-op and you can deploy it independently of any migration work.
  • Move one route at a time by adding it to the proxy's Laravel list. This is now your migration mechanism, and it is a configuration change.
  • Keep the rollback trivial. Reverting one route to legacy must be a config change and a reload, not a deployment. You will use this.
  • Do not route on anything clever. Path prefixes are enough. Routing on user segment or feature flag sounds appealing and doubles the states you must reason about.

This single piece of infrastructure is what converts an eighteen-month gamble into a series of one-week decisions.

Sessions and Authentication: Solve This First

The first genuinely hard problem, and the one that stalls migrations that skipped it. A user must be able to log in on a legacy page and stay logged in when the next request lands on Laravel.

  1. Move session storage somewhere both applications can read — Redis or the database — before you migrate any route.
  2. Agree a serialisation format. Two PHP applications with different framework versions do not necessarily serialise a session identically. Test this explicitly rather than assuming.
  3. Share the cookie domain and path, and align the cookie name.
  4. Have one system own authentication. Usually Laravel, once its login route is migrated, with the legacy application reading the session rather than writing it.
  5. Test session expiry and regeneration across the boundary. Logging out on one side and remaining logged in on the other is a security bug, not an inconvenience.

If you take shortcuts anywhere, do not take them here. A session bridge that works 99% of the time produces intermittent, unreproducible logouts that will consume more engineering time than the rest of the migration combined.

The Database Boundary

The pragmatic answer for most migrations: both applications share one database, and you do not attempt to redesign the schema during the migration.

This offends people, and it is right. Migrating the code and the schema simultaneously means every problem has two possible causes, and it removes your ability to move a single route independently. Get onto Laravel first; improve the schema afterwards, when you have one codebase and can change it with confidence.

  • Map the legacy schema with Eloquent models as it is, including the table names you would never choose.
  • Write to the same tables, so both systems see the same truth with no synchronisation layer to go wrong.
  • Be careful with legacy triggers and stored procedures — they are frequently undocumented business logic that will fire under Laravel too.
  • Introduce migrations for new tables only. Do not let Laravel's migration system take ownership of the legacy schema mid-project.
  • Watch for legacy code writing timestamps or IDs in ways Eloquent does not expect. This is a common source of subtle bugs.

What to Migrate First

The sequence matters more than the pace.

  1. Something low-risk and visible — a static page, a contact form, a help section. The goal is to prove the routing, session and deployment machinery end to end, not to deliver value.
  2. New features, from now on. Everything built after day one goes in Laravel. This is what makes the migration self-funding: the roadmap pays for the new system's growth.
  3. High-change areas next. Whatever the team edits most often benefits most from being in the maintainable codebase, and the effort pays back immediately.
  4. Read-heavy customer-facing pages, where you get performance and SEO wins alongside the migration.
  5. Checkout, payment and order processing last. Highest risk, highest cost of error, and by then your team has migrated a dozen simpler things.
  6. Admin and back-office last of all, unless it is actively obstructing. Internal users tolerate ugliness; customers do not.

The instinct is to start with the worst module. Resist it. Starting with the hardest thing means your first migration is also your first encounter with every infrastructure problem at once.

Keeping the Roadmap Moving

This is the whole point, and it needs deliberate protection.

  • Set a standing split — say 70% roadmap, 30% migration — and hold it. A migration that consumes all capacity becomes a business problem within a quarter, and business problems get cancelled.
  • Make each migrated route deliver something. Fix a known bug, improve the page, add a small feature. A migration that delivers no visible value for six months loses its sponsor.
  • Report progress in routes migrated and legacy files deleted. Deleting code is the only unambiguous evidence that a strangler-fig migration is working.
  • Do not touch the legacy code except to fix bugs. Every improvement to a system you are removing is money burned.

The Failure Modes

  1. Stalling at 60%. The easy routes are done, the hard ones remain, and the pain has reduced enough that urgency evaporates. Now you maintain two systems forever, which is worse than either. Agree up front what triggers finishing the job.
  2. Building an abstraction layer between the two systems. It feels like good engineering and it is a third system to maintain, which will outlive the migration it was meant to serve.
  3. Migrating the schema at the same time. Doubles the variables in every incident.
  4. No deletion discipline. If legacy code is not being removed as routes migrate, you are not migrating, you are duplicating.
  5. Underestimating the undocumented. Cron jobs, webhook endpoints, reports someone in finance runs monthly, an integration nobody remembers. Inventory these before you start; find them in production and they will find you first.

When Not to Do This

Strangler fig is not universally correct. Do not use it when the legacy application is genuinely small — under a few thousand lines, a straight rewrite is faster and the parallel-running machinery is overhead you do not need. Do not use it when the legacy system is being retired wholesale rather than replaced. And do not use it when the business logic itself is what needs to change; migrating logic you intend to discard is work performed twice.

This is the pattern behind most of our Laravel development work on inherited systems, and it sits alongside the assessment step we describe in inheriting a legacy PHP codebase. Our Laravel platform practice and custom PHP modernisation work cover both halves of the problem.

Frequently asked questions

How long does a strangler-fig migration take?

Longer in calendar time than a rewrite would claim, and it delivers value throughout rather than at the end. For a substantial application, expect 12–24 months of part-time capacity alongside normal roadmap work — with the important difference that stopping at any point leaves you with a working system.

Can both applications really share one database?

Yes, and for most migrations they should. Changing the schema at the same time as the code means every bug has two possible causes and you lose the ability to migrate one route at a time. Move to Laravel first; improve the schema when there is one codebase left.

How do we keep users logged in across both systems?

Move session storage to Redis or the database before migrating anything, align the cookie name, domain and path, and verify that both PHP versions serialise the session identically. Have one system own authentication and the other read it. Test expiry and regeneration across the boundary explicitly.

What should we migrate first?

Something low-risk and visible, purely to prove the routing, session and deployment machinery works end to end. Then all new features, then the areas your team edits most often. Checkout and payments last. Starting with the hardest module means meeting every infrastructure problem at once.

What if the migration stalls halfway?

This is the most common failure, and it happens because the pain reduces enough to remove urgency once the easy routes are done. Agree the finishing condition before you start, report progress as legacy files deleted rather than features shipped, and hold a fixed capacity split so it never becomes optional.

Get the Sequence Reviewed

The routing, session and sequencing decisions determine whether this works. We will review yours before you commit engineering to it. Talk to our team; we reply within a business day.


Have a project like this?

Tell us what you're building and where it's stuck. We'll reply within one business day with an honest read on scope, sequence and cost.

  • An honest read on scope, sequence and cost
  • A reply within one business day
  • No obligation, no sales sequence

Protected by Cloudflare Turnstile. We never share your details.