Modernization Roadmap
What this is and who it’s for
This is how to plan and sequence the modernization of a legacy government system across multiple years without betting the agency on a big-bang rewrite. It is written for the agency CIO or senior tech lead who owns a system that everyone agrees is old, who has been asked “so when do we replace it,” and who needs an answer that survives contact with a budget cycle and a change of administration. The short version: you do not replace it all at once, you do not modernize everything, and you treat modernization as a capability you fund continuously rather than a project you finish. This runbook gives you the assessment, the strategy choices, the incremental-replacement pattern, and the multi-year sequencing to make that real.
Prerequisites
Two artifacts must exist before this runbook is useful. Without them you are guessing, and a roadmap built on guesses is the thing that gets cut first.
- A documented current-state inventory. What systems you have, what each one does, who depends on it, what it runs on, and who can still maintain it. If this does not exist, build it before you build a roadmap.
- A target architecture. Where you are trying to get to, so each modernization move points somewhere. Use the Reference Web Application Architecture as the default target state and the Reference Integration Architecture for how the new and old systems talk during the transition.
The practice
Modernization is four moves in order: assess the portfolio, choose a strategy per system, replace incrementally, and sequence across budget years. Do them in that order. The most expensive mistake in this space is skipping straight to “rebuild it” before anyone has asked whether the system is worth modernizing at all.
Assess the portfolio first
Not everything is worth modernizing, and pretending otherwise is how budgets evaporate on the wrong systems. Score every system in the inventory on three axes: business value (how much the agency and the public depend on it), risk (how likely it is to fail or become unmaintainable, including the bus-factor on people who understand it), and effort (what it would cost to modernize). The disposition falls out of the scores — high value plus high risk is where you spend first; low value plus low risk you leave alone; low value plus high effort is a candidate to retire, not rebuild. Capture this in the portfolio-assessment table in Reference implementation and revisit it every budget cycle, because risk rises as people leave and platforms age.
The output of assessment is a disposition per system, not a feeling. A system everyone complains about may score low enough on business value that the right move is to retire it, and a quiet system nobody mentions may be the one carrying the most unmanaged risk.
Choose a modernization strategy per system
There is no single modernization strategy — there is a strategy per system, chosen from the disposition. The framing below is the common “6 R’s” plus retire. Pick deliberately; the cheapest viable option that clears the risk is usually the right one.
Rehost
Move the system to new infrastructure with no code changes — the classic “lift and shift” onto cloud VMs. Use it when the risk is the underlying hardware or data center, not the application itself, and you need to exit a facility on a deadline. It buys time and removes one risk; it does not modernize the application, so pair it with a plan or you have simply moved the problem. See the lift-and-shift pitfall in the Reference Web Application Architecture.
Replatform
Move to new infrastructure with minimal, targeted changes — swap a self-managed database for a managed one, containerize the app, update a runtime version. Use it when small changes unlock large operational wins without touching the core logic. It is the highest-leverage low-risk move for a system that is fundamentally sound but operationally heavy.
Refactor
Improve the internal structure of the code without changing its external behavior. Use it when the system does the right thing but is hard to change safely, and you need it maintainable before you can do anything else with it. Refactoring is rarely a roadmap line item on its own; it is the work that makes the other moves possible.
Rearchitect
Materially change how the system is structured — split a monolith, introduce an API tier, separate the data store — while keeping the same broad capability. Use it when the architecture itself is the constraint on scaling, integrating, or changing the system. This is significant effort; justify it against a concrete limit you are hitting, not a preference for newer patterns.
Rebuild
Rewrite the system from scratch against the target architecture, preserving the capability but none of the code. Use it only when the existing system cannot be evolved to where you need it and no commercial product fits. Rebuild is the highest-risk option and the one most likely to never ship — see the rewrite trap below, and run it through Build vs. Buy before committing.
Replace
Retire the custom system and adopt a commercial or shared-service product that covers the capability. Use it when the function is not a differentiator for the agency — payroll, ticketing, content management — and a product exists that meets the requirement. Replacing trades build risk for integration and configuration work; decide it explicitly with Build vs. Buy.
Retire
Turn the system off. Use it when assessment shows the business value no longer justifies any spend, and confirm nothing depends on it before you do. Retiring is the cheapest modernization there is, and the one teams forget is on the menu.
Replace live systems incrementally with the strangler fig
When the disposition is rebuild or replace and the system is live, the default pattern is the strangler fig: stand up the new system alongside the old one, put a facade in front that routes traffic, and migrate one slice of functionality at a time until the legacy system is starved of traffic and can be switched off. You never take the whole system down, every increment is independently shippable and reversible, and you can stop or re-sequence between increments as priorities change. The facade is the load-bearing piece — it is the single seam where you decide, per request, whether the legacy or the new system handles it.
┌──────────────────────┐ │ Users │ └───────────┬──────────┘ │ ▼ ┌──────────────────────────┐ │ Facade │ routes per │ (router / proxy / API │ capability: │ gateway) │ old vs. new └───────┬───────────┬──────┘ migrated │ │ not yet migrated slice ▼ ▼ ┌────────────┐ ┌────────────────┐ │ New │ │ Legacy │ │ system │ │ system │ │ (slice 1..n)│ │ (everything │ └──────┬─────┘ │ else) │ │ └────────┬───────┘ ▼ ▼ ┌──────────────────────────────┐ │ Shared / migrating data │ │ (anti-corruption layer keeps │ │ new model clean — see │ │ Integration Architecture) │ └──────────────────────────────┘
Over time: more slices move to "new", legacy traffic drops to zero, then the legacy system is switched off and the facade is removed.Keep the new system’s data model clean by putting an anti-corruption layer between it and the legacy data and contracts, so the old system’s quirks do not leak into the new one — the pattern lives in the Reference Integration Architecture. The strangler fig only finishes if every increment actually ships to production behind the facade; an increment that lands in a branch but not in front of users has not strangled anything.
Sequence the work
The first slice decides whether the whole effort builds momentum or stalls, so choose it for value and low risk, not for technical interest. You want a slice that is visibly useful to users or the agency, small enough to ship in one phase, and self-contained enough that its data and dependencies do not drag the whole legacy system along with it. Ship it, measure it, and use the result to fund the next slice. After the first slice, sequence by the portfolio scores — highest value-and-risk first — and re-sequence every cycle as the assessment changes.
Carry data migration through every slice rather than saving it for the end. Each increment migrates the data it needs, runs against migrated data in production, and proves the migration before the next slice begins. Leaving migration to the end converts a series of small, tested moves into one enormous untested one at the worst possible moment.
Fund and phase across budget years
A multi-year roadmap has to map onto how the state actually appropriates money, or it is fiction. Maryland’s budget operates on a [VERIFY Maryland budget cycle] fiscal year, which means each phase of the roadmap must fit a funding window and deliver something defensible within it. [FILL IN: confirm Maryland’s fiscal-year boundaries, appropriation timeline, and any multi-year capital-funding mechanisms available for IT modernization.] Phase the roadmap so that each budget year funds a coherent set of slices that ship and show value, rather than a slice of a slice that produces nothing until year three. Build the dollar figures for each phase from Total Cost of Ownership, not from build cost alone, so the business case survives scrutiny across cycles.
Manage the risk of the transition
The transition is the risky part, and three controls keep it survivable. Use all three on any slice that touches live data or live users.
- Parallel-run. Run the new slice alongside the legacy one and compare outputs before you cut over, so you catch divergence while the old system is still authoritative.
- Rollback. Make every increment reversible at the facade — flip the route back to legacy if the new slice misbehaves — and never ship a slice you cannot back out.
- Data migration as you go. Migrate, verify, and run on migrated data per slice, so a migration problem surfaces on one slice rather than across the whole system at cutover.
Avoid the rewrite trap
The single most common way government modernization fails is the big-bang rewrite: a multi-year effort to rebuild the whole system at once that ships nothing until the end, runs over budget, and is cancelled before it lands. The strangler fig exists specifically to avoid this — it forces value into production continuously and makes “stop here” a viable outcome at every phase. If a proposed plan has no user-visible delivery until a date more than a budget year out, it is a big-bang rewrite wearing a roadmap’s clothes; break it into shippable slices or do not start it.
Reference implementation
Three forkable artifacts. Copy them into your planning repo, fill in your systems, and keep them under version control so the roadmap is reviewable like code.
Portfolio-assessment scoring table
Score every system, derive the disposition, sort by where risk and value are highest. Use a consistent scale (for example 1–5) so scores are comparable across systems.
| System | Business value | Risk | Effort | Disposition ||-------------------------|----------------|------|--------|---------------------|| Permitting (legacy) | 5 | 5 | 4 | Rebuild (strangler) || Internal HR portal | 2 | 4 | 3 | Replace (COTS) || Payroll | 5 | 2 | 5 | Replatform || Public records search | 4 | 3 | 2 | Rearchitect || Legacy reporting tool | 1 | 2 | 2 | Retire || Document store | 3 | 3 | 1 | Rehost (then plan) || [FILL IN: your systems] | - | - | - | - |
Scale: 1 = low, 5 = high. Disposition is derived, not assigned by preference.High value + high risk → modernize first. Low value → retire or replace.Revisit every budget cycle; risk rises as people and platforms age.Strangler-fig routing diagram
The facade-and-route pattern from The practice, as a forkable template for documenting which slices have moved.
[ Users ] → [ Facade / router ] │ ┌──────────────┼──────────────┐ │ migrated │ migrating │ not yet started ▼ ▼ ▼[ New: slice A ] [ New: slice B ] [ Legacy: slices C..Z ] │ │ │ └──────► [ Anti-corruption layer ] ◄─── keeps new model clean │ [ Data (migrating per slice) ]
Track per slice: route owner (old/new), parallel-run status,rollback path, migration status. A slice is "done" only when itsroute points at the new system in production and legacy traffic is zero.Multi-year phased roadmap template
Phases aligned to budget years, each delivering a shippable, measurable outcome. Adjust the year boundaries to the verified Maryland fiscal cycle.
| Phase | Budget year [VERIFY] | Slice(s) | Strategy | Funded? | Measurable outcome ||-------|----------------------|-----------------------|-----------|----------|----------------------------|| 0 | FY[FILL IN] | Inventory + target | — | Y | Assessment + roadmap done || 1 | FY[FILL IN] | First valuable slice | Strangler | Y | Slice live, KPI measured || 2 | FY[FILL IN] | Next 1–2 slices | Strangler | [VERIFY] | Slices live, legacy ↓ || 3 | FY[FILL IN] | Highest-risk slice | Rebuild | [VERIFY] | Risk retired, data migr. || ... | ... | ... | ... | ... | ... || N | FY[FILL IN] | Final slice + cutover | Strangler | [VERIFY] | Legacy off, facade removed |
Each phase must ship something users or the agency can see within its budget year.Each phase's cost comes from Total Cost of Ownership, not build cost alone.A phase with no funding plan is a wish, not a roadmap line.Common pitfalls
- The big-bang rewrite that never ships. Symptom: a multi-year plan with no production delivery until the final phase, already slipping. Fix: break it into strangler-fig slices that each ship within a budget year, so “stop here” is always a viable, value-preserving outcome.
- Modernizing the easy stuff while the real risk sits untouched. Symptom: the team is busy upgrading a low-value system because it was convenient, while the high-value system with a single remaining maintainer ages another year. Fix: sequence by the portfolio scores — highest value-and-risk first — not by what is pleasant to work on.
- No measurable first slice, so momentum dies. Symptom: a year in, leadership cannot point to anything users got, and the next budget request is hard to defend. Fix: pick a first slice that is visibly valuable and ship it with a KPI, so the result funds the next slice.
- Data migration left to the end. Symptom: every slice shipped against the legacy data store, and the plan assumes one large migration at cutover that has never been rehearsed. Fix: migrate and verify per slice so the system runs on migrated data continuously and the final cutover is small.
- Modernization treated as a one-time project, not an ongoing capability. Symptom: the roadmap “finishes,” the team disbands, and three years later there is a new legacy system. Fix: fund modernization as a standing capability and keep the portfolio assessment alive every budget cycle.
- A roadmap with no funding plan. Symptom: a clean technical sequence that no one has mapped to appropriations or fiscal years. Fix: phase the roadmap onto the verified Maryland budget cycle and attach a Total Cost of Ownership figure to each phase before presenting it.
Procurement notes
Multi-year modernization almost never fits one procurement. Each phase that involves a rebuild, a replacement product, or new hosting typically requires its own contract action, and the procurements should be phased to match the roadmap rather than committed all at once — that keeps the agency from being locked into a vendor for work it has not yet scoped or funded. Write each phase’s statement of work to the slice it funds, and carry the modernization sequence through into the SOW so the vendor’s deliverables map to shippable increments — see How to Write a Good SOW. Where a phase is a replacement, run the Build vs. Buy decision before the procurement, not inside it.
The Maryland-specific contract vehicles, the relationship between procurement timelines and the fiscal cycle, and any master contracts available for IT modernization work are [FILL IN]/[VERIFY]. Do not assume a single procurement can carry a multi-year roadmap; confirm the phasing rules with procurement before committing the schedule.
Maintenance
Owner: [FILL IN: runbook owner] · Last reviewed: 2026-05-31 · Next review: 2026-08-31