Legacy Modernization
Legacy Modernization is the disciplined program — not a single pattern — of evolving outdated systems toward target architecture using Strangler Fig, Branch By Abstraction, ACL,…
Introduction
Legacy Modernization is the disciplined program — not a single pattern — of evolving outdated systems toward target architecture using Strangler Fig, Branch By Abstraction, ACL, data migration, and organizational change. At Uber, modernization means keeping rides running in São Paulo while replacing the dispatch core that predates microservices — with measurable milestones, not a PowerPoint target state.
Real production story
Uber's dispatch platform started as a Python monolith on a single PostgreSQL cluster. By 2017 it handled matching, pricing, and driver incentives for 75 countries — but regional outages cascaded globally because there was no bulkhead. Leadership funded "Project Helix": modernize to regional microservices over 24 months.
The first attempt was a 14-month rewrite branch — abandoned after LatAm big-bang caused 47 minutes of failed matches. The second attempt combined Strangler Fig (route new cities to new stack), ACL (translate legacy driver state to new model), and incremental data migration (dual-write driver availability). Staff architects owned a modernization runway with quarterly decommission targets. After 20 months, 88% of trips ran on the new regional stack; legacy dispatch served only legacy incentive rules scheduled for retirement in Q3.
Business problem
Business pressure: Uber's marketplace must expand to new cities weekly while legacy dispatch limits regional isolation, deploy velocity, and fault containment. Modernization is a business continuity program — not an engineering side project.
- Revenue at risk: Every minute of failed matching in NYC or São Paulo is measurable lost GMV and driver churn.
- Engineering velocity: 300+ engineers blocked by monolith merge queue; regional teams cannot ship without global regression risk.
- Compliance / trust: Regulators in EU and India require data residency — monolithic shared DB fails compliance review.
Architecture overview
Legacy Modernization in production is a program with: target architecture ADR, slice inventory ranked by risk/value, pattern selection per slice (strangler / abstraction / ACL / rehost / replace), data migration strategy, and decommission calendar. Success is measured by % traffic on target stack and legacy LOC deleted — not milestones on a Gantt chart.
- Definition: Systematic evolution from legacy to target architecture using incremental patterns and organizational alignment.
- When to adopt: Legacy blocks business goals (compliance, scale, velocity) and big-bang is unacceptable risk.
- When to defer: Legacy meets SLOs, change rate is low, and modernization cost exceeds 3-year business value.
- Operability: Modernization dashboard: traffic %, parity error rate, legacy API surface area, decommission dates.
Architecture motivation
Why architects care: Legacy modernization is portfolio management of patterns, not heroics. The naive alternative — single big-bang rewrite — concentrates risk and historically fails at Uber scale.
- Force: Legacy cannot meet quality attributes (regional isolation, deploy frequency, data residency) for next 3-year roadmap.
- Constraint: Rides must never stop; drivers and riders have zero tolerance for "migration weekend."
- Outcome: Phased modernization with pattern mix per slice, quarterly decommission milestones, and executive-visible progress metrics.
Internal architecture
Uber Helix modernization program — multi-pattern portfolio:
Modernization Program (24 months)├── Wave 1: New cities → Strangler (100% new stack)├── Wave 2: Driver availability → Branch By Abstraction + dual-write├── Wave 3: Pricing rules → ACL from legacy rule engine├── Wave 4: Matching core → Strangler + regional bulkheads└── Wave 5: Incentive engine → Replace (greenfield, read legacy read-only)Per slice:ADR → pattern → parity → canary → decommission → legacy delete
Data flow
Dual-write driver availability: driver app heartbeat → new regional service writes PostgreSQL + async sync to legacy monolith via ACL-translated event → reconciliation compares availability bitmap every 30s → alert on drift >0.1%.
- Write path: new stack authoritative for migrated regions; legacy authoritative for unmigrated — router decides.
- Read path: matching reads regional cache fed by new stack; legacy fallback for unmigrated cities only.
- Async path: trip completion events backfill analytics warehouse from both stacks during transition.
interface ModernizationSlice {id: string;pattern: "strangler" | "abstraction" | "acl" | "replace";trafficPercent: number;paritySlo: number; // max diff ratedecommissionDate: string;}const PROGRAM: ModernizationSlice[] = [{ id: "latam-new-cities", pattern: "strangler", trafficPercent: 100, paritySlo: 0, decommissionDate: "2024-06-01" },{ id: "driver-availability", pattern: "abstraction", trafficPercent: 72, paritySlo: 0.001, decommissionDate: "2024-09-15" },{ id: "matching-core", pattern: "strangler", trafficPercent: 45, paritySlo: 0.0001, decommissionDate: "2025-03-01" },];function modernizationHealth(): { onTrack: boolean; blockers: string[] } {return PROGRAM.map((s) => ({slice: s.id,ok: s.trafficPercent >= targetFor(s.decommissionDate) && parityBelow(s.paritySlo),}));}
System design diagram
Two diagrams show the Legacy Modernization topology and the primary request/event path used in production at scale.
Production code example
Modernization program dashboard API — aggregates slice health for staff review:
// Program health endpoint — consumed by exec dashboard + weekly arch reviewapp.get("/api/modernization/health", async (_req, res) => {const slices = await db.sliceStatus();const legacyLoc = await git.countLines("dispatch-legacy/");res.json({trafficOnTarget: weightedAverage(slices, "trafficPercent"),legacyLocTrend: legacyLoc,atRisk: slices.filter((s) => !s.parityOk || s.decommissionSlipped),nextDecommission: slices.sort(byDate)[0]?.decommissionDate,});});
Enterprise case study
Uber Project Helix — 20-month modernization: Combined strangler, abstraction, and ACL with program office tracking traffic % and legacy LOC. LatAm big-bang failure became the cautionary tale that unlocked incremental funding.
- Before: Global monolith; 47-min LatAm outage from big-bang; 14-month abandoned rewrite branch.
- Decision: Multi-pattern program with quarterly decommission gates; no big-bang without 4-week production parity.
- After: 88% trips on regional stack; regional outage blast radius contained; new city launch 3× faster on target stack.
Trade-offs
- Program overhead vs chaos: Modernization office adds process — prevents duplicate failed big-bangs.
- Multi-pattern complexity: Different slices use different patterns — document in single program dashboard for executive clarity.
- Short-term velocity vs long-term: Dual-run slows feature delivery 15–20% — communicate as investment with decommission dates.
Security considerations
Security is architectural: Modernization doubles auth paths during dual-run — regional mTLS, data residency, and driver PII handling must be consistent across legacy and target.
- Identity: Unified driver/rider identity service; both stacks validate JWT from same issuer.
- Data: EU trips stored in EU region only — router enforces residency before write.
- Supply chain: Target stack images signed; legacy deploy frozen except critical patches.
Scalability analysis
Scale dimensions: Uber plans modernization across 10,000 cities, 5M drivers, and regional compliance — each wave must scale independently without blocking the next.
- Horizontal scale: Target stack is regional from day one; legacy global monolith shrinks geographically.
- Hot spots: NYC and São Paulo dominate trip volume — migrate high-value regions only after parity proven in mid-size cities.
- Cost: Program budget includes 18 months dual-run infra + 2 FTE platform team for router/ACL — ROI via reduced outage cost and faster regional launch.
Failure scenarios
What breaks: Big-bang pressure from leadership before parity; slice teams pick incompatible patterns; decommission dates slip → permanent dual-run.
- Executive big-bang pressure: Staff architect presents SLO burn analysis — quantitative no.
- Pattern mismatch: Program office reviews pattern selection in weekly architecture forum.
- Decommission slip: Auto-escalate when legacy API surface grows instead of shrinks two quarters in a row.
Staff engineer insights
- Modernization is a product with executives as stakeholders — traffic % and decommission dates belong in QBR slides, not just Jira.
- The LatAm big-bang failure is your best asset in architecture reviews — use it to kill big-bang proposals with data.
- If legacy API surface area grows quarter over quarter, the program is failing — escalate immediately.
Interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1AdvancedQuestionHow do you structure a 24-month legacy modernization program at Uber without losing executive support?+
Answer
Follow-up
2AdvancedQuestionWhen do you choose replace (greenfield) vs strangler for a legacy module?+
Answer
Follow-up
3AdvancedQuestionDesign organizational ownership for a multi-pattern modernization program.+
Answer
Follow-up
Architecture review questions
- Are quality attributes (latency, availability, consistency) explicit with SLOs for Legacy Modernization?
- Is the failure/degraded mode documented — including what happens when dependencies are down?
- Are boundaries and ownership clear on an architecture diagram a new engineer understands in 10 minutes?
- Is there an ADR capturing alternatives considered and why they were rejected?
- Can this design scale 10× on traffic and 3× on engineering headcount without a rewrite?
- Security: authn/authz, encryption, and blast radius reviewed at every external interface?
Summary
Legacy Modernization at Uber scale combines Strangler Fig, Branch By Abstraction, ACL, and replace strategies under a governed program with quarterly decommission gates. Keep rides running, make progress visible to executives, and kill big-bang proposals with the LatAm postmortem data.