Back to Insights
Engineering

Strangling the Monolith: Modernizing Legacy Systems with Next.js

Victoria Zikiye
11/2/2025
10 min read

Key Takeaways

  • Don't rewrite from scratch; migrate incrementally.
  • Use the 'Strangler Fig' pattern to replace functionality piece by piece.
  • Leverage Next.js Rewrites to route traffic between new and old systems.
  • Maintain SEO ranking and user experience throughout the transition.

The directive is clear: 'We need to modernize.' Perhaps your frontend is stuck in AngularJS, or your backend is a sprawling PHP monolith that no one fully understands anymore. The intuitive reaction is to declare bankruptcy: burn it down and start over.

This is almost always a mistake.

Total rewrites are notorious for going over budget, missing deadlines, and—worst of all—failing to reach feature parity with the old system. While you are busy rewriting existing features, your competitors are shipping new ones.

Enter the Strangler Fig

Martin Fowler coined the term Strangler Fig Application based on the banyan trees that grow around a host tree. They start as small vines, gradually enveloping the host until the original tree dies and rots away, leaving a new, strong structure in its place.

In software terms, this means building a new application around your legacy system, gradually intercepting traffic and handling it with modern code, until the legacy system can be safely decommissioned.

Why Next.js?

Next.js is uniquely suited for this strategy because of its powerful hybrid routing capabilities and edge middleware.

The Migration Architecture

  1. The Facade: We deploy a Next.js application as the main entry point (the reverse proxy) for your domain.
  2. Incremental Routing: We configure Next.js to handle specific routes (e.g., /dashboard, /new-feature) while proxying everything else back to the legacy server.
  3. Shared State: We implement strategies to share authentication state (cookies/JWTs) between the two systems so the user never knows they are crossing a boundary.

Example: Next.js Rewrites

The configuration in next.config.js is deceptively simple but incredibly powerful:

module.exports = {
  async rewrites() {
    return [
      {
        source: '/:path*',
        destination: 'https://legacy-api.com/:path*',
      },
    ]
  },
}

With this setup, you can carve out one route at a time. Today, you rewrite the About Us page. Tomorrow, the Checkout flow. The legacy system continues to hum along, handling the traffic you haven't migrated yet.

Benefits of this Approach

  • Risk Mitigation: If a new feature breaks, you can instantly revert routing to the legacy system.
  • Immediate Value: You can ship a modern, performant mobile experience for critical flows immediately, without waiting for the entire backend to be rewritten.
  • Team Morale: Developers get to work with modern tools (React, TypeScript, Tailwind) on new features, rather than spending 100% of their time maintaining legacy code.

The Result

After 6-12 months, you look back and realize that 90% of your traffic is hitting the Next.js app. The legacy monolith involves only a few vestigial admin endpoints. You have successfully strangled the monolith, all while continuing to ship value to your customers.