PHP to Node.js Migration Without Downtime

Key takeaways

  • Migrate incrementally, not with a big bang rewrite: keep PHP running, build Node.js module by module, and switch traffic only when each module is proven.
  • Use the strangler fig pattern: put an API gateway such as nginx or Kong in front of both systems and route paths to Node.js one at a time.
  • Start with a shared database or a read replica for most migrations, and reserve event sourced sync for high write volume or strict data isolation requirements.
  • Run comparison tests that feed the same inputs to the PHP and Node.js systems and diff the outputs, catching behavioral drift before users see it.
  • Keep PHP running as a fallback for 30 to 60 days after go live while the team monitors error rates, latency, and user feedback.

Migrating from PHP to Node.js is one of the most common legacy modernization projects we undertake for UK clients. Whether you're running Laravel, Symfony, or a custom PHP monolith, the decision isn't whether to migrate but how. A big bang rewrite rarely works. A phased, parallel run approach almost always does.

1. Rewrite vs Refactor: Why Full Rewrites Usually Fail

Before committing to a PHP to Node.js migration, the first question is: do you need a full rewrite or can you refactor in place? A full rewrite means building a new system from scratch and switching over. It sounds clean. In practice, it carries enormous risk.

Most rewrites fail because they underestimate three things: undocumented business logic, integration complexity, and user tolerance for change. Your PHP system has evolved over years. Edge cases, workarounds, and implicit rules live in code that nobody fully understands. Rebuilding from scratch means rediscovering, or losing, that logic.

The safer approach is incremental migration. You keep the old system running. You build the new Node.js system module by module. You switch traffic only when each module is proven. If something breaks, you roll back in minutes, not weeks.

2. The Parallel Run Approach: Strangler Fig Pattern

The strangler fig pattern, coined by Martin Fowler, is the standard technique for legacy system modernization. You introduce a facade or API gateway in front of both systems. New functionality is routed to the Node.js service. Older routes stay on PHP. Over time, you migrate routes one by one until the PHP application is fully replaced, then you retire it.

In practice, this means:

  • Deploy an API gateway (nginx, Kong, or a simple Node.js reverse proxy) that routes requests based on path or header.
  • Build new Node.js endpoints for the highest value or highest traffic features first.
  • Point the gateway at the new endpoints when ready; PHP handles the rest.
  • Run both systems against the same database (or a replicated copy) during the transition.

Your users never see a single "maintenance window." Business continues uninterrupted.

3. Database Migration Strategy

The database is usually the hardest part. PHP systems often use MySQL or PostgreSQL with schema designs that evolved organically: denormalized tables, missing indexes, implicit relationships. You have three main options.

Option A: Shared database. Both PHP and Node.js read and write the same database. Easiest to implement, but you must avoid schema changes that break either system. Best when the schema is relatively clean.

Option B: Read replica for Node.js. Node.js reads from a replica; writes still go through PHP. Use this for read heavy migrations (e.g. dashboards, search, reporting) while you rebuild write paths later.

Option C: Event sourced sync. PHP emits events on writes; Node.js consumes them and maintains its own read optimized store. More complex, but gives you a clean boundary and the ability to reshape data for the new system.

For most UK clients, we start with Option A or B. Option C is reserved for systems with high write volume or strict data isolation requirements.

4. API First Architecture

Your new Node.js system should be API first from day one. That means clear REST or GraphQL contracts, versioned endpoints, and documentation. Even if your current PHP app serves HTML directly, the Node.js replacement should expose APIs. A React or Vue frontend can then consume those APIs, and so can future mobile apps, partners, or internal tools.

Design the API to match how the business works, not how the old PHP code was structured. Use this as an opportunity to fix naming, consolidate endpoints, and remove legacy cruft. The API becomes the source of truth for the new system.

5. Handling Undocumented Business Logic

Every legacy system has logic that isn't in the documentation. It might be in a 300 line function, a cron job, or a trigger in the database. Finding it requires a disciplined discovery phase: code review, database audits, and interviews with long tenured staff.

We typically allocate one week of technical audit before writing any new code. We trace user flows end to end, document every integration, and flag anything that looks like implicit business rules. That output becomes the specification for the Node.js rebuild. Skipping this step is the most common cause of post migration bugs.

6. Testing Strategy During Migration

Testing must run continuously. For each migrated module, we build:

  • Contract tests: the new API matches the expected request/response shape.
  • Integration tests: the new module works correctly with the shared database and downstream services.
  • Comparison tests: for the same inputs, the new system produces the same outputs as the old one. Run both in parallel and diff results.

Comparison tests are especially valuable. You can replay production like data through both systems and catch behavioral drift before users do.

7. The 30 to 60 Day Stabilization Period

Go live isn't the finish line. Plan for a 30 to 60 day stabilization period where the old PHP system stays running as a fallback. Your team (or ours) is on standby. Critical bugs get fixed within hours. You monitor error rates, latency, and user feedback. Only when you're confident do you fully retire PHP.

At RG INSYS, we build this period into every legacy redevelopment engagement. It's not an add on; it's how we ensure zero downtime migrations actually stay zero downtime when something unexpected happens.

Migrating from PHP to Node.js is a significant undertaking, but it doesn't have to be a gamble. With the right approach (parallel run, shared database where appropriate, API first design, thorough discovery, and a proper stabilization window) you can modernize your legacy system without disrupting your business.

Frequently asked questions

Can you migrate from PHP to Node.js without downtime?

Yes, by using a parallel run approach based on the strangler fig pattern. An API gateway sits in front of both systems, routes migrated paths to new Node.js endpoints, and leaves the rest on PHP. Users never see a maintenance window, and if a module misbehaves you can roll back in minutes rather than weeks.

Should you rewrite a PHP application from scratch or migrate it incrementally?

Migrate incrementally in most cases. Full rewrites usually fail because they underestimate undocumented business logic, integration complexity, and user tolerance for change. Keeping the PHP system running while you build the Node.js replacement module by module lets you prove each piece before switching traffic to it.

How do you handle the database during a PHP to Node.js migration?

Most migrations start with a shared database, where both systems read and write the same tables, or a read replica, where Node.js reads and PHP still handles writes. Event sourced sync, where PHP emits events that Node.js consumes into its own store, is reserved for high write volume or strict data isolation.

How long should the old PHP system stay running after go live?

Plan for a 30 to 60 day stabilization period with the old PHP system kept running as a fallback. During that window the team monitors error rates, latency, and user feedback, and fixes critical bugs within hours. PHP is fully retired only once the new Node.js system has proven stable.

Sources and further reading

  • Strangler Fig, Martin Fowler (2024). The original description of gradually replacing a legacy system by growing new components around it.
  • Strangler Fig Pattern, Microsoft Azure Architecture Center. How a facade routes requests between legacy and new systems, and how shared data stores are handled during migration.
  • Strangler fig pattern, AWS Prescriptive Guidance. Proxy layer routing, anti-corruption layers, and data synchronization when migrating a monolith incrementally.
  • Introduction | Pact Docs, Pact. Contract testing explained as checking each side of an integration in isolation against a shared agreement.
  • PHP: Supported Versions, PHP.net. Active and security support end dates for each PHP release branch.
  • Node.js Releases, Node.js. Release lifecycle and the guidance that production apps should run only Active LTS or Maintenance LTS releases.

Related Articles

Planning a PHP to Node.js migration?

We've delivered zero downtime legacy migrations for UK recruitment platforms, telecom enterprises, and SaaS companies. Get a free scope, timeline, and cost estimate within 48 hours.

Book a Free Consultation