Microservices Architecture transition readiness

02.24.20 03:42 PM By Juan Peredo

 Is your team ready for Microservices?

Team meeting taking place

Over the last few years, microservices have gained popularity as a way to improve team productivity while increasing application maintainability. The rallying cry behind this architecture has been led by internet giants that successfully migrated from a traditional monolithic application to thousands of microservices. But would this architecture benefit your team and make your products more flexible and nimble?

What are microservices? 

While there are several definitions of what exactly is a microservice architecture, the basic high level infrastructure is built around small pieces of code with just one responsibility and that perform a single task. Those individual pieces of code are combined to achieve more complex tasks. You can think of it as building blocks. While the individual building blocks cannot do much on their own, they can be used to build grand structures


How do microservices compare to traditional applications?

Traditional applications are built as a single code base. All the pieces are intertwined into a single package which, at a simplified high level, interacts with an end user on one side and the database on the other. Microservices applications are built using a multitude of small codebases that work together to deliver results to the end user. Each microservice could be connected to its own database to manage its own data, though they do not need to be. For example, a simple number adding microservice would receive numbers as inputs and return a result without needing a database.

Traditional vs Microservices Architectures
Figure 1 - Comparing architectures

The clear advantages and reasons why microservices are becoming so popular are:

  • Maintainability: Maintaining small pieces of code with few, if any, dependencies is simpler than maintaining a large code base with lots of dependencies

  • Reusability: Microservices are small pieces of code with a single purpose in life and can easily be reused in other projects

  • Modularity: Since each service is independent of the rest of the application, it can de be upgraded and deployed independently

  • Fault isolation: Properly designed microservices isolate issues from the rest of the application

  • Scalability: Microservices are scaled independently without scaling the whole application

  • Cost: As a corollary to the scalability of microservices, scaling small microservices requires less resources than scaling the whole application. This translates to lower costs, especially in the world of cloud computing, where costs are based on resource usage.


Understanding microservices complexities
Having explored microservices architecture and its potential benefits, how do you ensure that your team can quickly capitalize on these benefits? Unfortunately, a number of projects have attempted to move to this new paradigm only to waste months of work and thousands of dollars only to end up with a more complicated and less manageable system. To avoid this, there are a number of concepts your team should understand to ensure they are properly prepared for the change.

Modularity comes at a price

Managing usage of hundreds of microservices requires a very structured approach to services design, documentation and API versioning

  • Dependencies: Service dependencies should be minimized. The architecture's advantages disappear as number of dependencies increase and each service can no longer be managed independently. Reusability, fault isolation and independent scalability benefits vanish as well
  • Boundaries: The ability to reuse services and combine them to build applications are great advantages of this architecture. But this can quickly devolve into an unmanageable mesh of interconnected services, where no one truly understands which services are being used where. This puts significant stress when trying to debug issues, upgrade services or even trace the lifecycle of data in an application. Instead, design your microservices to be naturally grouped by logical context boundaries (e.g. customer services, product services, etc...). Intercommunication within a boundary could occur normally while communication outside the boundary would be done using an intermediary, potentially a pub/sub queue for example

Figure 2 - Bounded microservices context design

Increased architecture complexity

While individual microservices are significantly less complex than a traditional application, the overall architecture of an application increases significantly in mainly two ways:

  • Number of moving parts: Beyond the large number of microservices that need to be maintained, additional software modules are required to allow the microservices to work and perform reliably. In our simple high level overview in figure 1, we introduced a reverse proxy (to allow simple external communication with the external world) and queues (to allow messaging between services). But that is only the tip of the iceberg. We could also introduce logging/monitoring agents, API gateways, secret management and multiple databases among other things.

  • Network traffic: In a traditional architecture, applications move data internally and unless the application itself fails, data is guaranteed to be processed. With microservices, that guarantee no longer exists. Communication between microservices is dependent on a network transport across potentially multiple network nodes. Since networks introduce both latency and failures, it is important for the microservices to be built with additional resiliency and the ability to withstand unreachable downstream services. Items like circuit breakers, retries and timeout management become critical for the application to function properly and manage errors gracefully


Debugging and monitoring

In traditional applications, debugging/monitoring is straightforward and developers are intimately familiar with these processes. However, with microservices, debugging/monitoring workflows change significantly.

  • Debugging: When and error takes place in a distributed application, it is not as simple as attaching the debugger and stepping through the code: First you need to determine where the in the chain of microservice calls the fault occurred. Then, you need to bring up all the microservices involved in processing the relevant information. Finally you need to trace the data through each of those processes until you finally determine the root cause of the issue.

  • Logging and Monitoring: In this new paradigm, it is no longer possible to have a single logging and monitoring point built into the application. Instead, each microservice writes its own logs and has different monitoring needs. Thus, the needs arises for external log aggregators and monitors.


Preparing your team to move to Microservices

As discussed above, there are significant differences between developing and maintaining a traditional monolith application and a microservices application. As you prepare to move your team into a microservices infrastructure it is important to ensure the team members are ready to make the switch.

  • Time: Do not underestimate the time requirements to get the team up to speed. Proper training and exposure to the new paradigm is very important to the project's success. There is a steep learning curve required before they can be as productive as they were in a traditional setting. Team members need to have enough time to switch their mindset to this new paradigm or they will eventually fall back to what they know and the project will end up with a large number of tightly coupled microservices which are hard to maintain and almost impossible to upgrade

  • Need: Evaluate whether you really need a microservices architecture. The project needs to be big enough to warrant moving to this new methodology. Small to medium projects will probably not benefit as much because any gains from the new architecture will probably be wiped out by the increase in architecture complexity. Alternatively, check if the application components can be reused in other projects. In that scenario, microservices may indeed be the way to go

  • Design: Schedule extra time to design the first set of microservices, ensure they are decoupled and self standing. Also, while the name microservices implies that services should be potentially as small as a function, this does not have to be the case. Study your environment, requirements and business needs. Would it be better to just make mini-services? Or services that are just bounded by a business function (eg: customers service, products service instead of customer kpi service or product inventory service).

  • Automation: Embrace CI/CD and automation. Without automation to create/update your infrastructure and code base (everything as code), managing a large ecosystem quickly gets out hand.

  • Tooling: Research and evaluate tools already available that could simplify your path. There is a large ecosystem of tools aimed squarely at the management of distributed applications. Below is a small sample of what is a rich and plentiful ecosystem. Which tools you use depends on your requirements 

List of cloud services that help develop and manage microservices
Figure 3 - Distributed systems ecosystem tools sample

Microservices architecture opens a world of possibilities when it comes to large distributed systems. It provides a number of significant advantages over traditional monolith architecture. However, like most things in life, it does come with some significant baggage. While this is not a silver bullet, it is a compelling new tool in the software development arsenal. 

Juan Peredo