Microservices are nothing new. After being deployed successfully by mega-companies like Netflix, many growing engineering organizations gravitate towards this architecture as an aspirational symbol of success. This journey is known to many as the “monolith to microservices” migration.
A few companies (Spotify) have the clairvoyance to adopt microservices from the get-go and may never have to endure such arduous re-architecting. Other companies (Etsy) double down with their monoliths (a.k.a founding architecture) and scale into multi-billion dollar organizations. Many others opt for the long journey from monolith to microservices with roughly the following scenario:
We’ve seen immense success with our monolithic application and we are ready turn up the dial on growth. We need to explore new product lines, hire more developers, and increase velocity. To enable all of these wonderful things, we’ll start transitioning our monolith to microservices. This architecture will enable autonomous workstreams, failure isolation, flexible scaling, and {insert other microservices benefits}.”
I am not a fan of the term “microservice architecture” because it has become increasingly difficult to define. In regards to software, your system is either distributed—or not distributed. With many of us working in the context of distributed computing, I would venture to guess that you’ll find it impossible to use a textbook definition (microservices vs. service-based vs. event-based) to describe your architecture. You may describe your system as a “hybrid” or “ball of mud.”
While microservices are wonderful in principle, many software engineers are intimately aware of their challenges in practice. Parodies like this are a little too close to reality.
When pursuing grand endeavors, engineering leaders often forget to explicitly address organizational concerns. These constraints have the potential to block progress more so than any other technical issue.
Monolith To Microservices Vs. Your Organization
#1 — Executive (Budget) Alignment
Supporting microservices is expensive.
This is expensive not only with respect to compute/storage/network costs, but also with respect to operations and head count. This is not as simple as instructing software engineers to pivot how they develop. For example, a dedicated team may need to be formed to support the microservice “framework” itself. What are common tools for deployment and monitoring? How will dependencies be consistently upgraded and patches be successfully installed if we plan to have 100s or 1000s of services?
This investment should be discussed early with leadership, specifically with the executives that control the budget. For budgets that are controlled by non-engineers, spend time developing the business case and getting firm commitments to support the effort. Leadership background matters. A worthwhile investment to engineers can easily be perceived as a poorly-defined cost to others.
#2 — Experience
Has anyone done something like this before?
Fundamental software architecture changes are not to be taken likely. During times of migration, seemingly trivial decisions influence the software for years and years into the future.
Before embarking on the journey, have you located an individual (or collective set of experiences) in your organization that has been through a monolith to microservices journey before? This means actually participating in similar migrations (even if it they were unsuccessful) and not just living pleasantly in a post-migrated world. These experiences are rare.
#3 — Philosophical Alignment
Software developers are opinionated. Experienced engineers hold philosophies molded over time by unique companies, projects, and teams.
Before embarking on this migration, key engineers need to be bought in and aligned with the vision. This alignment is deeper than sharing signatures on a document. It is a perpetual alignment and re-alignment of philosophies surrounding how to approach problems.
A common philosophical difference in software development is the spectrum between generalized and specific thought.
Generalized developers love interfaces and can’t get enough of C++ templates. These engineers constantly try to integrate their solutions into “frameworks” and always seem to find common patterns across wildly different domain use-cases.
Specific developers don’t care much for Java Generics and are annoyed with obfuscated code. Not all their classes need to be implementing an interface and duplicated code is not that big of a deal. Straight to the point is their motto.
Now imagine that two of your most-senior, most-experienced developers sit on opposite sides of this spectrum. Up until now, these engineers have balanced each other out and have designed the successful application you have today. However, each of these engineers would have a drastically different approach to problem solving as your software systems and headcount grow.
Organizationally, how will you resolve these philosophical differences? How can you be confident this migration will be executed in a consistent and enjoyable manner?
#4 — Ownership
Given your large and successful monolith, how would you rate it on clarity of ownership? Can the majority of modules be assigned to various teams or is there a kitchen sink of forgotten endpoints?
Ownership is not a technical issue. It’s an organizational issue and should be addressed before any attempt is made at a migration. If critical steps in the strategy depend on changes to an unowned part of the codebase, it will be a headache to get that work planned and executed.
Ownership is psychological. Teams and engineers go to great lengths to skirt around code that they do not own. “This is everyone’s code” only works at small levels of organizational scale. Lack of ownership especially hurts when you’re trying to make fundamental changes to your software.
#5 — Decomposition Vs. Morale
Many engineers would not describe migration work as glamorous. Usually, the first step in a monolith to microservices migration is decomposition. Before the system can feasibly be re-architectued, modules need to be split out and put behind interfaces so implementations can safely be manipulated. For developers, this may feel like they are picking up rocks just to put them down somewhere else—the rocks are still the same rocks!
How can this be broken down into manageable pieces? How will you set up your teams for success?
Poor strategies around decomposition work will rapidly demoralize teams. If you are not strategic with execution steps, this work will turn into a slog and you will burn through your engineers. How do you expect a team to carve out modules in the codebase when half of it is unowned?
Carefully plan and assign this work while paying attention to motivations and incentives.
Conclusion
The monolith to microservices migration is a long journey. You’ll experience gratifying wins along with unwelcome additions to your technical debt. These foundational changes are an organizational effort just as much as they are a technical lift. If the company does not fully support this work, no amount of software ingenuity or pool of 10x programmers will help.