I inherited a warehouse management system that ran on a VAX. The hardware was older than most of the developers on the team. The business wanted a modern cloud platform yesterday, and we drew up an eighteen month plan to replace the whole thing in one dramatic cutover. Looking back, that was our first mistake. We spent months writing requirements documents, building screens that mirrored the old ones almost exactly, and then discovered during user acceptance testing that half of the workflows didn't actually match what the floor supervisors did every day. The system had been patched so many times over twenty years that nobody, not even the people using it, could describe the full logic anymore.

We scrapped the big bang approach after a particularly painful mock go-live where the inventory counts went negative in three warehouses. Instead, we put an API layer in front of the old system. It sounds simple, but wrapping a VAX application with a modern REST interface was like teaching a horse to use a smartphone. We had to build an adapter that translated JSON calls into terminal screen scraping. Ugly, yes, but it worked. That wrapper became the foundation for everything else. We could then replace one module at a time while the rest of the business kept humming.

That pattern, often called the strangler fig, is the strategy I now recommend almost reflexively. You don't rip out the old system. You grow a new one around it, route traffic gradually, and only decommission pieces once their replacements have proven themselves in production for months, not days. For the warehouse project, we started with the receiving module because it was small and self contained. We ran it in shadow mode for six weeks, comparing its output to the legacy system line by line. Then we switched one warehouse, then two, then all of them. Each step felt boring, and that was the point.

There's another piece that gets overlooked, and that's treating data as a first class citizen. We tried a big one time data migration at the start and it almost killed us. Addresses were stored differently in every customer record, some had embedded control characters, and a surprising number of products had been discontinued but still had active inventory. We eventually built a continuous sync process that streamed changes from the legacy database to the new one, allowing us to keep both systems alive during the transition. That meant we didn't need a perfect migration because the data was always moving and reconciling in near real time.

The human side matters more than any architecture diagram. I made the mistake of not including the warehouse supervisors in the design sessions until late in the project. They knew which screens were slow, which buttons nobody used, and which error messages meant call the vendor immediately. Once we started inviting them, the new system stopped being a threat and became something they had a hand in shaping. Modernization fails far more often from poor communication than from bad code.

These days I tell clients to start small, wrap before you replace, and keep the old system running as a safety net for much longer than feels comfortable. The goal isn't to win a race to the cloud. It's to retire the legacy system without anyone really noticing because the new one already does the job better. And if you can do that, you have earned the right to call yourself an enterprise architect.