BlueOC Tech

Published

Modernizing Legacy Systems Through APIs: What to Move First

Modernizing a legacy system means changing software while the business continues to depend on it. APIs can make that transition more manageable, but progress depends on how teams define business boundaries, assign data ownership and handle failure. This article explores how to select the first workflow to move, evaluate whether the migration is working and plan for the eventual retirement of the old capability.

Modernizing Legacy Systems Through APIs: What to Move First

An order appears as cancelled in the customer portal, but the warehouse still prepares it for dispatch. Both systems are available, and the API request returned successfully. The problem sits between them: the software agrees that a message was received, while the business still has two different versions of what happened.

This hypothetical situation captures a central challenge of legacy modernization. Connecting systems is one part of the work. Establishing which system makes a decision, which record is authoritative and how other systems respond takes considerably more thought.

APIs can provide useful boundaries for gradual change. To make those boundaries effective, teams need to start with a business capability they can understand, measure and eventually operate independently.

Choose a workflow with a clear business outcome

A modernization programme often begins with a list of technical problems: an ageing framework, a difficult database or a release process that takes too long. These are legitimate concerns, but they offer limited guidance about what should move first.

A better starting point connects the technical constraint to a business outcome. Perhaps a customer service team needs fewer manual checks before approving a return. Perhaps a distributor needs to onboard partners without modifying its core ordering system each time. The first migration should create an improvement that someone outside the engineering team can recognize.

Consider a distributor whose support staff repeatedly investigate order status across several applications. A consolidated order-status capability could be a useful first step because its benefit is observable: customers find answers more easily, and support staff spend less time reconstructing an order’s history.

However, the team must still investigate where each status originates, how quickly it changes and what it means. “Dispatched” might mean that a shipping label has been created in one application and that a carrier has collected the parcel in another. Exposing both through a new API would preserve the confusion.

Before selecting a workflow, assess three things together: its business value, the dependencies that must move with it and the consequences of failure. A modest capability with clear ownership can provide a stronger first release than a highly visible feature whose rules are scattered throughout the system.

Use the API boundary to control change

Microsoft’s Strangler Fig guidance describes gradually replacing capabilities while an intermediary routes requests to either the existing application or the replacement. This allows the migration to proceed in stages, with both systems operating during the transition. Microsoft also notes that the intermediary introduces its own performance, reliability and operating-cost considerations.

For the distributor, this might mean routing order-status requests to a new service while order creation and fulfilment remain in the existing application. The customer-facing contract can stay stable as the implementation behind it changes.

That contract needs to describe behaviour as well as data fields. It should establish what each status means, how fresh the information is, which users can access it and what response to expect when a dependency is unavailable.

An API that returns a timestamp and a status code can be technically complete while remaining operationally ambiguous. An API that explains whether the information is current enough for a customer promise gives its consumers something more useful.

The boundary should also make future change easier. If every adjustment to the new capability still requires coordinated releases across several legacy modules, the team has more dependency work to do.

Decide who owns each change to the data

From request to confirmed outcome.png

Reading information through a new service is different from allowing that service to change it. The move from viewing an order to cancelling one introduces a more consequential question: which system has authority to accept the cancellation?

In the distributor example, the warehouse may already have started picking. A cancellation request must therefore be evaluated against fulfilment state, and the customer needs a clear distinction between “request received” and “cancellation confirmed.”

During migration, teams should explicitly assign authority for each business operation. Copies of the data can exist in several systems, but the rules for accepting a change must be clear. Where multiple writers are unavoidable, the design needs an explicit method for resolving conflicts.

A practical migration record might look like this:

DecisionExample for order cancellation
Who accepts or rejects the request?The service responsible for cancellation rules
Which information determines eligibility?Current fulfilment state and applicable order policies
How is the result communicated?A confirmed state change and an event for downstream consumers
What happens while the result is uncertain?The customer sees a pending request with a defined follow-up process
Who resolves inconsistent records?A named operational owner using a reconciliation workflow

These decisions belong in the delivery scope. Leaving them implicit makes it difficult to distinguish a temporary delay from a failed business transaction.

Design for partial failure

A common integration problem occurs when a system updates its database and separately sends a message to another system. One operation may succeed while the other fails.

AWS documents the transactional outbox pattern as one way to address this problem. The application records the business change and an outgoing event within the same database transaction; a separate process then publishes the event. Consumers must still account for possible duplicate delivery, and the implementation needs to handle ordering where it matters.

In an order-cancellation workflow, this can help ensure that an accepted cancellation has a durable event waiting to be delivered. It does not mean that every downstream system updates immediately or that the warehouse can always reverse work already underway.

Those remaining conditions need product decisions. How long can the portal display a pending state? When should an operator intervene? If dispatch has already occurred, does the request become a return rather than a cancellation?

Retries also need careful treatment. If a customer resubmits a request after a timeout, the system should be able to recognize the repeated operation and avoid applying its business effect twice. The interface, processing logic and support workflow should agree on what a repeated request means.

These details determine whether the migration feels dependable to the people using it.

Prove the behaviour before expanding the rollout

The first production release should provide evidence about both technical performance and business behaviour. Response times and error rates are useful, but they do not reveal whether customers received the correct answer or whether staff had to repair transactions manually.

For the distributor, relevant measures could include incorrect status reports, unresolved cancellation requests, reconciliation effort and support contacts per order. The team should establish the baseline before routing users to the new capability.

A gradual rollout can limit exposure while those measures are evaluated. Routing should preserve the consistency boundaries of the workflow: keeping an order or customer on a coherent processing path may be more appropriate than randomly assigning each individual request.

Where comparison is useful, read requests can sometimes be evaluated against both implementations to identify differences. Write operations require more care because executing both paths could create duplicate effects. Any parallel evaluation needs to control notifications, payments, inventory changes and other actions outside the application.

Differences should then be investigated with domain experts. The old system may contain an important exception, an obsolete rule or a defect. Reproducing every result without examining its purpose can carry unnecessary complexity into the replacement. The feature-parity discussion in Patterns of Legacy Displacement similarly cautions against treating the existing feature set as an unquestioned specification for the new system.

Treat rollback as a data problem

Rollback restores traffic and data coherence.png

Routing traffic back to the old application is only one part of recovery. Once the new capability has accepted changes, the old system must be able to understand the resulting state.

Suppose the replacement introduces a cancellation state that the legacy application cannot represent. Switching traffic back may restore a familiar screen while leaving staff unable to process the affected orders correctly.

Before cutover, the team should define what remains reversible, how new transactions would be reconciled and which changes require a forward repair. Recovery exercises should include realistic business records, rather than checking only that an earlier application version can start.

Microsoft’s migration guidance also makes the distinction explicit: removing legacy data structures and synchronization mechanisms makes rollback more difficult and can require restoring objects and replaying changes. Decommissioning therefore needs its own validation point.

A useful recovery plan names the person who can halt expansion, the conditions that trigger that decision and the team responsible for resolving transactions already in progress. This makes rollback an operational capability that can be exercised under pressure.

Finish by removing a dependency

Temporary integration components are often necessary. Adapters, synchronization jobs and routing layers allow the business to keep operating while capabilities move. Their purpose and eventual removal should be visible in the modernization plan.

Thoughtworks authors writing in Patterns of Legacy Displacement describe this as transitional architecture: software introduced to support the journey towards the intended system, including components that will later be discarded.

For each migrated capability, define what retirement requires. This may include moving reporting consumers, replacing scheduled jobs, resolving historical-data access and removing the old write path. A capability is difficult to retire when these dependencies remain invisible until the final stage.

The programme should track both the business improvement delivered and the dependencies removed. More endpoints, services or cloud resources can indicate activity, but the stronger evidence is that a team can now make a useful change with fewer coordinated releases and less operational repair.

For BlueOC, this is the practical lens through which to approach API modernization: identify the workflow that needs to improve, make its rules and ownership explicit, and build a transition that the business can operate confidently. Each release should deliver a measurable benefit and create a clearer boundary for the next change.

References

Ready to turn ideas into impact?

Ready to turn ideas into impact?

Talk to our team about your business challenge or next project.

Our Latest Insights

View All Posts