How to introduce microservices in a legacy environment

It is critical to balance risk with reward and, when it comes to microservices, embrace an evolutionary approach and process


While no consensus exists on how to define microservices, it is generally agreed that they are an architectural pattern that is composed of loosely coupled, autonomous, fine-grained services. The services are independently deployable and communicate using a lightweight mechanism such as HTTP/REST. Enterprises that need to make frequent changes to their systems—and where time to market is paramount—need to be investigating how to introduce microservices in their legacy environments to realize a digital transformation that drives tangible business results.

The benefits and potential hurdles associated with adopting microservices are well documented. On the plus side, the modular and independent nature of microservices enables improvements in efficiency, scalability, speed, and flexibility. Detractors, however, frequently point to management and security challenges, especially when they pertain to customer-facing applications and services.

Like virtually all technology decisions, it is critical to balance risk with reward and, when it comes to microservices, embrace an evolutionary approach and process. The same is true for implementing microservices that can increase product and service quality, ensure systems are more resilient and secure, and drive revenue growth. In the first of this three-part series, I’m going to explain how business and technology leaders can smoothly and successfully introduce microservices into a legacy environment.

It’s all about the monkey

A key requirement of microservices design is to focus service boundaries around application business boundaries. A keen awareness and understanding of service and business boundaries helps right-size services and keeps technology professionals focused on doing one thing and doing it very well.

In my experience, the larger the organization the greater value microservices architecture can deliver, but only if executed in a systematic, enterprise-wide fashion. Fortune 500 organizations tend to have a significant proliferation of legacy technologies and should strive to simplify deployment, along with applying continuous integration and delivery of microservices. All too often, enterprises focus their efforts on buying tools, implementing a small proof-of-concept or other “quick wins” that likely aren’t the most effective place to initiate microservices strategies.

Astro Teller, the “Captain of Google Moonshots,” has a humorous description about where to begin when solving a large and complex problem. He advocates that companies should avoid allocating all their resources on the easy stuff and instead start by addressing the hard problems; he calls it “tackling the monkey first.” The monkey, when deploying microservices in a large, established environment, is understanding and decomposing the legacy systems.

Decompose the legacy environment by identifying seams

In the second part of this series I’ll cover domain-driven design (DDD), but for now it is important to understand two concepts found in DDD: bounded contexts and domain models.

Any problem domain is composed of several bounded contexts with models sitting inside them. The bounded contexts provide a level of protection and isolation of the models. In addition, the bounded context provides an interface to the model and controls what information is shared with other bounded contexts. For example, in an e-commerce application some of the bounded contexts may be ordering, pricing, or promotions.  

In his 2004 book, Working Effectively with Legacy Code, Michael Feathers presented the idea of a seam as a way to identify portions of code that can be modified without affecting the rest of the code base. This older notion of seams can be extended as a modern method to divide a monolithic system into bounded contexts from which services can be quickly created. 

Uncovering seams in applications and building bounded contexts is an important first step in breaking down the monolith. A few suggestions to identify seams:

  • Review the current code base. When reviewing the current code base and any artifacts, it’s critical to realize that this is only a starting point. The code is often redundant and difficult to understand.
  • Interview domain experts. This is a key step to learning where the seams are and identifying bounded contexts. Having domain experts that understand what the business should be doing, not just what the system currently does, is critically important. 
  • Understand the organizational structure. Often, organizational structure will provide clues to where the seams can be found.

Once bounded contexts are identified, along with the programming language and environment that support them, creating packages and subpackages that contain these bounded contexts should closely follow. This approach will afford a careful analysis of package usage and dependencies, which are paramount to fully and quickly understanding and ensuring that testing and instrumenting code is being done properly.  In addition, there are some standard design patterns that should be followed:

  • Open host pattern. Exposing legacy systems via JSON/HTTP service. Here the isolated legacy system is exposed through an API that returns JSON.
  • Anti-corruption layer (ACL) pattern. A translation layer, or bridge layer, is built between the legacy environment and the microservices code. This pattern can be effective for short durations, but it can be costly to maintain over time.

That’s how microservices should be introduced in a legacy environment. In the next post, I’ll address domain-driven design before showing how to put it all together for a more flexible and scalable infrastructure.

This article is published as part of the IDG Contributor Network. Want to Join?