whoami engineering practice that migrates legacy stacks without breaking production

Off the legacy stack.
Onto something modern.

We help engineering teams move off WordPress, jQuery, AngularJS, Rails 4, PHP 5/7, and other 2010-era stacks — incrementally, with feature flags, with rollback paths, and without the 6-month code freeze most teams brace for.

40+ migrations shipped zero rollback incidents in 18 months remote-first, US/EU hours fixed-scope sprints

Four engagements. Each one ends with you owning the stack.

No retainers, no managed-service lock-in. We finish, we hand it off, we leave documentation your engineers will actually read.

svc_01

Framework Migration

jQuery, AngularJS, WordPress themes, server-rendered PHP — moved onto React, Vue, Next.js, or Astro. Strangler-fig pattern, route by route. The old stack keeps serving traffic while the new one comes online behind feature flags.

svc_02

Database & API Modernization

MySQL 5 to Postgres. SOAP and untyped REST to GraphQL or tRPC. Memcached to Redis. We migrate the data with parity checks, then rewire the consumers behind a versioned API edge so nothing inside the org breaks.

svc_03

CI/CD & Infrastructure

Off bare-metal, off brittle Jenkins, off the 40-minute deploy. Onto Fly.io, Render, or Vercel with GitHub Actions, preview environments, canary deploys, and the observability your on-call rotation has been quietly begging for.

svc_04

Code Audit & Roadmap

One week. We read the code, the build, the deploy logs, and your incident history. You get a risk-ranked migration map with sprint estimates, dependency graphs, and a hand-off doc your CTO can present in a board meeting.

Common from → to.

A non-exhaustive list of stacks we've moved teams off of in the last 24 months. If yours isn't here, ask — we've probably touched something close.

WordPress (theme + plugins)Astro / Next.js + headless CMS
jQuery 1.x / 2.xVue 3 / React 18
AngularJS 1.xModern Angular / React
PHP 5.x / 7.xPHP 8.3 / Node / Go
Rails 4 (and 3, sometimes)Rails 7 / Hotwire
Custom in-house CMSSanity / Strapi / Payload
Bare-metal VPSFly.io / Render / Railway
Monolithic DjangoFastAPI + thin BFFs
Bootstrap 3 / 4Tailwind + shadcn/ui
Grunt / Gulp / BowerVite / Turbopack
MySQL 5.6 / 5.7Postgres 16
MemcachedRedis / Upstash

Five steps. No magic. No surprises in week 9.

Every engagement runs the same loop. The deliverables at each step are concrete — code, docs, dashboards — not slide decks.

01audit

Read everything before touching anything.

One sprint reading the repo, the build, the deploy logs, the last 12 months of incident reports, and the dependency tree. We meet with each engineer for 30 minutes. We end with a risk map.

deliverable: risk-ranked migration roadmap · dependency graph · sprint estimates
02plan

Decide what's worth migrating, what's worth deleting.

Not every module survives. We tag code paths as migrate / freeze / delete and get sign-off from your team before any keys are pressed. Then we draw the seams where the strangler will live.

deliverable: module tagging · seam contracts · feature-flag inventory
03strangler-fig

New stack runs beside the old, not on top of it.

We stand up the new application behind your existing edge (Cloudflare or similar). Routes flip one at a time. Both stacks live in the same repo or org so your team can read every diff. No fork, no parallel universe.

deliverable: edge routing · dual-running infra · CI parity gates
04migrate

Canary, verify, repeat. Boring on purpose.

Each route migrates behind a feature flag scoped to a percentage of traffic. We compare responses (HTTP status, body diff, latency) between old and new in real time. If parity breaks, traffic falls back to old automatically.

deliverable: canary deploys · parity tests · automated rollback · per-route flags
05verify

Cutover, observe, hand off.

DNS flips when 100% of traffic has been on the new stack for 7 days with no parity failures. We stay on-call for 30 days post-cutover, then check in at day 90 to look for regressions you might have missed.

deliverable: runbook · observability dashboards · 30-day support · 90-day check-in

Three recent migrations. Details changed, problems didn't.

Names and specific business metrics omitted by request. The technical narrative is verbatim from our post-mortems.

case_01 · b2b saas

AngularJS 1.5 dashboard → React 18 + Remix

beforeAngularJS 1.5, Grunt, Rails 4 API
afterReact 18, Remix, Rails 7 API
duration → 9 sprints (18 weeks)

The team had been quoted "12 months and a code freeze" twice. We migrated 47 routes behind feature flags, one workflow at a time. The Rails 4 API stayed in place for the first 6 sprints — we upgraded it on a separate track. Parity tests caught 14 behavioral differences nobody knew existed. Zero customer-reported regressions at cutover.

case_02 · e-commerce

WooCommerce monolith → Next.js + Shopify Hydrogen storefront

beforeWordPress 5, WooCommerce, 32 plugins
afterNext.js 14, Shopify backend, Sanity CMS
duration → 7 sprints (14 weeks)

Black Friday was non-negotiable. We froze new features in week 1 and ran storefront and checkout in parallel from week 4. The catalog migrated as a one-way ETL into Shopify; editorial content went to Sanity with redirects mapped 1:1 from the old WP slugs. Cutover was a DNS flip on a Tuesday at 10am. The team hit BFCM 11 weeks later with a 2.1s LCP, down from 6.4s.

case_03 · internal tool

Bespoke PHP 5.6 ops console → FastAPI + SvelteKit

beforePHP 5.6, jQuery, MySQL 5.6, no tests
afterFastAPI, SvelteKit, Postgres 16
duration → 5 sprints (10 weeks)

The console was running on a single VPS the original dev had set up in 2014, then left. We wrote characterization tests against the existing endpoints in week 1 — 280 of them — then used those as the parity oracle. The MySQL→Postgres migration ran as a logical replica for 3 weeks before cutover. The ops team noticed the new UI on Monday and asked us to make it slower so they could "see what was happening." We did not.

What we won't do.

There are good reasons to migrate. Most of the reasons we get asked aren't them. Here's what we'll push back on.

full_rewrite_that_goes_dark()

No 9-month branch-and-pray. If your team can't ship features during the migration, we've designed it wrong. Strangler-fig or nothing.

migrate_to_be_modern()

"We want to be on React" is not a business reason. We'll ask what's actually broken — perf, hiring, security, velocity — and migrate against that, not a vibe.

microservice_everything()

If your monolith works and your team is 8 engineers, we're not splitting it into 14 services. Modernize in place. Extract only where ownership boundaries demand it.

swap_for_resume_tech()

No moving you to Kubernetes because it's on someone's career roadmap. We pick the boring, durable choice your future team can hire for and operate.

black_box_handoff()

We don't ship code your team can't read or operate. Every PR runs through your review process. Pairing is built into every sprint. You own the keys from day one.

retainer_for_the_sake_of_it()

Migration ends. Our involvement ends with it. We're not interested in being a permanent vendor on your AP ledger. Healthy stacks don't need consultants forever.

Tech we work in.

Boring, well-documented, hireable. Nothing on this list will surprise your next engineering lead in 2027.

Next.js
Astro
Remix
SvelteKit
Rails 7
Django
FastAPI
Node.js
Go
PostgreSQL
Redis
Cloudflare
Fly.io
Vercel

From the engineering leads we worked with.

No marketing quotes. These are pulled directly from end-of-engagement retros, lightly edited for length.

They wrote 280 characterization tests against a codebase that had zero. That alone was worth the engagement. The migration was almost a side effect.

Priya R.VP Engineering · B2B SaaS (Series C)

We'd been quoted 12 months by two other firms. Daniel's team did it in 18 weeks and our engineers can actually maintain what shipped. No black box, no lock-in.

Marcus T.CTO · Logistics platform

The thing I appreciated most was getting pushback. We wanted to split the monolith. They told us not to. They were right. Saved us probably a year of pain.

Jen K.Engineering Lead · E-commerce

Questions we get on the discovery call.

Answered here so we can spend the call talking about your stack instead.

How do you migrate without downtime?

Strangler-fig pattern. We stand up the new stack alongside the old, route traffic incrementally behind feature flags, and verify parity at every step. The "cutover" is a DNS flip after weeks of dual-running — not a Big Bang launch.

Can you work with our existing engineering team?

Yes — that's the default mode. We pair with your engineers, write code in your repo, and submit PRs to your normal review process. We're not a black-box vendor and we don't operate fork-and-merge migrations. Knowledge transfer is built in, not bolted on.

What if our legacy code has no tests?

Common situation — maybe more common than tests existing. We write characterization tests against the existing behavior first, then use them as the parity oracle during migration. The new code has to produce the same output as the old code for the same inputs, byte-for-byte where it matters and observably-equivalent everywhere else.

How do you scope an engagement?

Every engagement starts with the Code Audit (1 week, fixed scope, fixed price). The output is a risk-ranked roadmap with sprint estimates. After that you can continue with us, hand the roadmap to your in-house team, or shelve it — no pressure, no follow-up emails.

What's your refund policy?

If the Code Audit deliverable isn't useful to you, we refund it in full. For longer engagements we bill in 2-week sprints — you can stop at the end of any sprint with no penalty. No annual contracts, no auto-renewals, no surprise SOWs.

Do you do ongoing development after migration?

Migration is the project. Ongoing dev is not our model — your team should own the new stack, full stop. We do offer 30-day post-cutover support included in every engagement, plus a 90-day check-in to address regressions or pipeline issues. After that, we're a phone call, not a retainer.

$ echo "ready_to_migrate" | mail team@rewireweb.co

Send us a 3-line stack description.

What you're on, what you'd like to be on, and what's blocking you. We'll reply within 1 business day with realistic timelines and what we'd ask in a 30-minute call.

// fixed price, no surprises — scoped on the intro call