Saturday, July 27, 2024

Microservices and Standards; Request / Response

Standards are essential for implementing a Microservice Architecture. In this article, I will focus on the structure of requests and responses involved in such an architecture.

It's important to remember that a microservice does not expose its API to the outside world. These microservice APIs are intended to be consumed within the context of the overall application. In fact, a microservice architecture is a design pattern where the implementation of an application's sub-domains is distributed across isolated, independent services. Since we are still dealing with a single, overarching domain, it’s important to ensure that certain data attributes in both request and response types are used consistently across the system.

Typically, a request enters the application’s domain through an API gateway. This entry point functions similarly to the API interface in a monolithic system. Ideally, we aim to define a single API that, through the use of attributes, can handle various functionalities within the system.

The API request is then passed to an application orchestration layer, which is responsible for applying rules, performing validations, and determining the best route (i.e., the appropriate microservice) before forwarding the request. In some cases, the orchestration layer may enrich the request with additional attributes of its own.

Once the request reaches a given microservice, it is processed. This may result in another request being generated—either to another microservice or to an external entity or system. Responses are then generated by the called services and eventually returned to the API gateway, which sends a final response back to the original client.

In many cases, the initial microservice may forward the request to another microservice, forming a chain of services involved in the processing pipeline—second, third, fourth, and so on. This process continues until a final response is produced, traveling back through the same route—first to the orchestration layer and finally to the API gateway. In complex applications, this can involve several, even dozens, of microservices before the final response exits the system.

To accurately correlate the various requests and responses, it is crucial that they all share a unique transaction ID. Additionally, it’s important to identify the originating client that initiated the request. Therefore, having a standardized base structure for both requests and responses across all microservices is essential for maintaining consistent and reliable processing throughout the system.

Transitioning to a Microservices Architecture - Part 2

Microservices and the Development Organization

by Rubens Gomes

Microservice architecture is based on the principles of modular systems that align with the domain-driven design (DDD) paradigm. That is, the architecture is divided into sub-domains, each with specialized responsibilities, and delineated from other modules by what is known as a bounded context. To develop deep expertise and effectively address the concerns of these sub-domains, it is ideal to have development teams composed of specialists in each particular domain. These teams become the owners of the microservices within their respective sub-domains. This type of organizational structure is key to successfully implementing a microservices architecture.

As stated in Conway's Law:

“Organizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations.”

The implications of Conway's Law are fundamental to the successful implementation of a microservices architecture. Because a microservice is a module with responsibility within a specific domain—and thus has a clear bounded context—assigning dedicated teams to work on specific sub-domains tends to naturally facilitate the development and maintenance of microservices.

In essence, what I’m emphasizing is that to achieve the best results from a Microservice Architecture, an organization must be structured around sub-domain expertise. Microservice architecture goes hand in hand with Conway’s Law. By structuring organizations around sub-domains, you naturally encourage the creation of applications that reflect the structure and purpose of the corresponding microservices. Communication within these expert teams becomes highly cohesive, focused, and aligned with the specific requirements of their sub-domain. This, in turn, supports the development of a clean and efficient Microservice Architecture.

In fact, one way to guide an organization toward a Microservice Architecture is to apply the Reverse Conway Maneuver (also known as Inverse Conway’s Law). This approach suggests that by organizing teams around sub-domain expertise, the system architecture will begin to reflect that structure—resulting in the natural emergence of a Microservice Architecture.


Tuesday, July 9, 2024

Why I Like Microservices

Why I Like the Microservices Architecture Style

By Rubens Gomes

In order to explain some of the reasons why I prefer the microservices architecture style, I’ve written this comparison between monoliths and microservices, based on over 30 years of practical, real-life experience in software development across both small and large companies.


Monolith Development Environment Setup

Setting up a development environment is one of the most important steps a developer must take when starting a new job. It involves not only configuring tools (e.g., IDEs, text editors), network access, databases, and source control, but—most importantly—creating an environment that facilitates the development and maintenance of the application.

This is, right off the bat, one of the issues I have with monolithic systems: monoliths are usually very complex to set up. I’ve had real-life experiences where it took over a week just to get a development environment ready for a single monolith application.

Monoliths are often tied to licensed platforms such as J2EE, include numerous libraries, have complicated builds involving multiple components, and use large, complex databases. Getting tests running and learning the entire business domain adds further complexity. Everything in a monolith is orders of magnitude more complicated than in a microservices setup.

In one job, it took me over two weeks to get my environment working for one of the department’s main monolith applications. The system used a J2EE backend server implemented on IBM WebSphere, which required a local installation and extensive configuration across multiple components: databases, system interfaces, and shared libraries. The build process itself was very complex, with different modules relying on various property configuration files.


Monoliths: Long Meetings and Long Releases

I remember, as a senior architect at a large enterprise, attending weekly meetings with project managers, QA leads, and department managers to review features being implemented for upcoming releases. The meeting room wall was covered with lists showing the lifecycle status of each feature.

As release dates approached, we had to coordinate what was ready, what was still in QA, and when we could potentially deploy. Everything took longer—development, testing, cross-team communication, orchestrating different projects, and aligning multiple parallel feature tracks. We also had to coordinate with the Operations team to schedule deployments.

This is, in my opinion, one of the greatest drawbacks of monoliths: how long it takes to get something into production. A single release could take months due to the number of steps and teams involved.

Often, we had to split features into different branches, each moving in parallel. While development was ongoing, production issues would arise, triggering the need for hotfix branches. To make things even more complicated, we had to manage operational logistics: when to deploy, who would deploy, at what time, and how to handle rollbacks if needed.


Microservice Development Environment Setup

Microservices, on the other hand, typically have smaller databases, fewer libraries, simpler business sub-domains, fewer tests, and significantly fewer lines of code. I’ve seen real-life cases where a contractor joined a team in the morning and by the afternoon had their development environment set up and was already coding on one or more microservices.

In my own experience, once we migrated from a monolith to microservices, everything became so much easier. Setting up a development environment in Eclipse or IntelliJ IDEA took only minutes. All I had to do was clone the microservice project, import it into Eclipse as a Maven project, and run a build via CLI or DevOps tools like Microsoft Azure. From the IDE, I could begin coding in no time.


Why Is It Easier to Work with Microservices?

Microservices are small, focused applications that are designed to do one thing—and do it well. You no longer have to juggle all the technologies, components, databases, and libraries that a monolith typically involves.

The build process becomes much simpler and faster since it doesn’t depend on various cross-cutting component libraries. Because microservices are focused on a specific sub-domain, the learning curve is much shorter. Our brains are better equipped to focus on one smaller, well-defined problem at a time—as opposed to having to understand a large, all-encompassing monolith.

Getting things up and running, writing tests, implementing features, delivering updates, fixing bugs—everything is so much faster and easier with microservices. You can stay focused on a specific business area and ensure features are delivered to production quickly. Testing is faster, and builds and deployments are simpler.

I’ve seen many cases where a pull request was approved in the morning and the code was in production the same day. Troubleshooting is also easier with microservices since logs can be scoped to individual applications, making it much simpler to trace issues.

Transitioning to a Microservices Architecture - Part 1

Transitioning to a Microservice Architecture – Part 1

By Rubens Gomes

I had the opportunity to serve as a technical lead during the implementation of the microservices architecture for the American Airlines Ticketing department from 2016 to 2023. The Ticketing department is responsible for the booking and payment processing of over 700,000 airline tickets daily. The company’s IT transformation began around 2017, and the ticketing team was among the first to have microservices running in production.

Transitioning to a microservice architecture involves significant changes—not only to the technical architecture and continuous integration/delivery pipelines, but also to the organizational culture and team dynamics. In a microservice architecture, teams become more independent and self-organized, each responsible for a specific part of the business domain. These teams develop deep expertise in their respective sub-domains and take full ownership of development, deployment, and production support.

In addition to these structural and organizational changes, a successful transition to microservices requires several critical foundational components. In future parts, I’ll elaborate on these elements and explain why they are essential for effectively implementing a microservices architecture.

Stay tuned for the next edition of "Transitioning to a Microservices Architecture – Part 2". I have much more to share on this topic, as I had the unique opportunity to witness—and help shape—a real-world microservices implementation from the ground up in a very large enterprise.