Skip to main content
Back to Blog
Development

Migrating a Legacy Pug/Express App to React + NestJS

NT

NeoCodeHub Team

February 1, 2026

We inherited a competitive intelligence application built with Express.js and Pug templates at PharmaEdge.ai. Every page navigation required a full server round-trip, the monolithic codebase made feature development slow, and there was no granular access control.

The Strangler Fig Approach

Instead of a risky big-bang rewrite, we used the strangler fig pattern — incrementally replacing Pug routes with React components while keeping the Express backend operational. Nginx routes traffic: new React routes go to the SPA, legacy routes still hit the Pug server. Over four months, we migrated one route at a time with zero downtime.

Cerbos for Fine-Grained Access Control

The old system had basic role checking hardcoded in middleware. Cerbos replaced this with policy-as-code — RBAC rules defined in YAML files and evaluated at the edge. This supports attribute-based access control without code changes, making it easy to add new roles and permissions.

Performance Results

Page load time dropped from 3.2 seconds to 0.48 seconds (85% improvement). Initial JavaScript bundle went from 2.5MB to 380KB through code splitting and lazy loading. Subsequent navigations happen in 120ms as SPA transitions instead of full page reloads.

Lessons Learned

Always migrate the API endpoint at the same time as the frontend route. Scope legacy CSS under a wrapper class to prevent conflicts with new styles. Audit every page for hidden server-side session dependencies before migrating.

Related Posts