Switching to a microservice architecture seems easy, but tech leaders tend to underestimate the complexity of the project and make disastrous mistakes.
Before transforming your monolithic system into microservices, or starting one from scratch, you need to carefully consider the technological and organizational challenges that will arise.
This post is for you if you want to:
We conducted 13 interviews with tech leaders from 5 different countries, from Israel to USA, before compressing their knowledge into this actionable post.
This post is really long! You can use the links below to jump to a specific part:
The biggest mistake you can make is to switch to a microservice architecture without having a clear goal. You need to understand and have real reasons why you want to do it.
“People go blindly into a lot of things: oh, docker is cool, microservice is great! It might not fit in every piece you build, you need to understand why you want to do it.” - Steven McCord, Founder and CTO at ICX Media
If you have a working system that works fine, then what is your driving force to change that?
Just because microservice architectures are hyped doesn’t mean you need to jump on the bandwagon. It might not be the best technological choice for your software.
“The first question I ask my clients when they ask me to help them implement microservices is, why? The answers I’m looking for are, “We want to change our system faster” and “We want to take advantage of cloud tech.” I make them aware that microservices, done right, are more expensive and harder than building a monolithic system. It does interesting things to your data and introduces a network into your data model, which can arbitrarily partition at any time, with data being lost. You expose yourself to the full fury of distributed computing.” - David Dawson, Systems Architect
“I wouldn’t necessarily go for microservices. I would go for medium-sized services, so not from a monolith to hundreds of services but instead bigger services that align with the engineering teams and the business verticals.” - Daniel Ben-Zvi, VP of R&D at SimilarWeb
If you don’t find the right balance between what’s a service, microservice, and function, you’ll either:
It’s crucial to have a very clear philosophy of how the microservice characteristic looks for your company.
How do you do it? A micro case study
“We determined what a microservice is by looking at what pieces of code, if changed, ended up creating exponential test cases. We started taking those out because our goal was to reduce the amount of testing we had do for every single change we make. If that is your goal, then what you define as a microservice is different than when somebody says, ‘I want billing to be a microservice.’” - Avi Cavale, Co-founder & CEO at Shippable
👉 Recommended reading: Microservices vs. Monolithic architecture
Scalability: You have small pieces you can analyse to see what requirement each piece has. It enables you to scale different parts of your application separately.
“The other big benefit for me is that I can scale these containers outside of any VM. I can put containers in any kind of configuration I want so I have complete portability of my application.” - Steven McCord, Founder and CTO at ICX Media
Easier maintainability: Let different teams work on different components in a more-or-less independent manner.
Deploying and configuring without much distractions: You can deploy and configure tiny pieces of your system without affecting other services. Multiple teams can deliver multiple results to production without interfering and stepping on each other’s’ toes.
Problem isolation: Much easier to isolate and detect problems.
Easier hiring: When you’re looking for developers or third-party providers, you only need to train them for a small part of the system.
Responsibilities are clearly defined: One team is responsible for a given microservice.
Deep knowledge: The team working on it knows it inside-out.
Wide variety of programming languages: You can use different programming languages, depending on what best serves the microservice's purpose.
Easier to oversee and understand: You can split your huge code base to smaller projects. This approach allows you and your team to understand the project and its code better.
Easier to open up components: It’s way easier to open up components or existing functionalities to new business units or external entities when the boundaries and interfaces are clearly defined.
Deployment and interoperability: The drawback here is that deployment and interoperability become chief concerns.
Too many programing languages: This can limit your code reusability as well as maintainability and it could make hiring more complicated.
Making components work together: You always need to ensure that your services are composed in a way they work together. Just think about changing a single endpoint which would break other depending services in older versions.
Harder to do integration tests of the whole system compared to a monolithic system where everything is in one place.
Architecture has to be well-thought through from the beginning: If there is too much cohesion among the services, you lose most if not all the advantages.
Requires more effort in communication: There is an associated cost related to the investment you have to make in terms of communication between the services. Lots of failures can happen between the communication of the services.
Difficult to monitor the whole system: You have a lot of pieces altogether which could be a nightmare to monitor.
Takes time to learn: Using a microservice architecture requires learning, and that takes time.
Complexity: Having more and more microservices makes the whole system more complex and harder to oversee the whole operation.
“All these pieces are lying around. If you don’t have very good engineering processes, you will end up with a whole bunch of things lying around that may never be used at all.” - Avi Cavale, Co-founder & CEO at Shippable
“Debugging production issues on a microservices-based platform is a completely different opera. Without proper monitoring, logging and tracing facilities, the complexity of your system grows significantly. It’s like going through a maze. Engineering practices and standardization become critical.” - Daniel Ben-Zvi, VP of R&D at SimilarWeb
Logging to one place is challenging. Third party log aggregation services like Loggly, Splunk or Heroku are very good solutions but they do come at very hefty price. In my experience telemetry specially centralized logging is a biggest pain. You have to think of verbosity level of each service. If you don't, you might end up paying 50-60% of your cost in logging infra only. (Sonu Kumar, Site Reliability Engineer at Microsoft)
When it comes to switching to a microservice architecture, these are the top challenges tech leaders and developer teams could face.
“Switching from a monolithic architecture to a microservice architecture is not something you can do all at once. If you have a monolithic server, you probably have repositories, deployment tasks, monitoring and many other things tightly set up around it. Changing that all together is not easy.” - Brujo Benavides, Ex-CTO at Inaka
What we did back then was to keep the monolithic server in place but any new addition was developed as a microservice, so that eventually things were drained out of the original server until it ended up being only the oldest and biggest of our microservices. (Brujo Benavides)
It can be pretty challenging to isolate components and services if they have been glued together since the beginning of a project. (Robert Aistleitner).
“There is no pattern; there are many different rules for splitting a system into microservices but no one will tell you how you should do it in case of your application. There is no two identical microservices.” - David Papp, Chief Architect at Recart
“The only way to split a monolithic system into microservices is to inspect the monolithic system first to see where it ‘hurts’ the most. These parts of the system should be taken out and transformed into a microservice.” - Andras Fincza, VP of Engineering at Emarsys
If you don't monitor appropriately, you won’t see how your system works. Monitor how all the pieces are working and what they’re doing. If you monitor your system, you can detect and solve problems easily. (Jose Alvarez)
Incrementally, module by module is the best way to split a monolithic system. If you want to do everything at once, you will certainly fail.
Tool tips for monitoring:
It’s not a technological decision. You’ll need to clearly state the benefits of a microservice architecture to persuade your company to reallocate resources. It’s a long, tedious process until a change like this is accepted in an organization, and the larger the organization, the longer that decision can take.
The best way to convince your organization to switch to a microservice architecture is to transform just one, non-critical part of your system into a microservice. This way you can demonstrate its advantages using a real, working microservice.
Developers have to spend a lot more time understanding what is an end-to-end scenario. They need to be familiar with the technologies and it might require switching mindsets, which takes time.
It is uncomfortable for people who have been working in a world where they can do end-to-end tests and now you’re suddenly breaking it down into small pieces. It’s more of a cultural change. (Avi Cavale)
Start with something very small, where you can really benefit from it and select something that’s not a critical part of your application. Get a small team and transform that part of the app into a microservice. Prove that it’s actually better and scale that out to the organization, step by step (Avi Cavale).
“I guess the biggest mistake you can make is that you haven't created an overview of the implications a change to a microservice architecture can have. There are a lot of moving parts that you have to include before actually starting to implement the new approach.” - Robert Aistleitner, VP of Engineering at Usersnap
“With a monolith, it’s easy to change an internal interface; you just refactor your code end to end and run your tests. With microservices, your API must be gold. It’s relied upon and you’re not necessarily aware of all your clients. Moving without API future proofing is going to create lots of headaches in the future. Also, make sure you have a distributed tracing system in place.” - Daniel Ben-Zvi, VP of R&D at SimilarWeb
“Avoid trying to switch to microservices without figuring out the platform and the dependencies. Also, believing that microservices are good because every microservice can be written in a different language is a bad practice.” - Viktor Tusa, DevOps Engineer at LogMeIn
“Sharing data between microservices is a big no-no. If two services are manipulating the same data, you will start experiencing consistency issues and disambiguate ownership.” - Daniel Ben-Zvi & Varun Villait
"Breaking an application into too many and too small pieces or forcing to transform a system into microservices that shouldn’t be a microservice - just because of the hype".- Csaba Kassai, Lead Developer at Doctusoft
Creating isolation between microservices enables them to be changed as fast as you need them to be. This generally requires isolation at several levels:
Runtime Processes: This is the most obvious, and one that’s commonly adopted quickly. Where before you had one process, now you have many. The primary cost here is adopting some form of distributed computing, which is hard to do right. This may lead you to adopting containerisation, event architectures, various http management approaches, service meshes, and circuit breakers.
Team/ Cultural. Separating teams, to give you autonomy, means you partition your human-to-human communication. This tends to lead to knowledge silos and duplication of work (a working out of the optionality vs resource efficiency choice). Recommended reading: Programming as Theory Building by Peter Naur
Data. The largest impact of adopting a distributed computing approach like microservices is in the way it affects your data. You have partitioned your data in some form, and so you need to re-integrate it at the system level to give the impression of “a system.” This gives you some interesting potential benefits in regard to scaling, but it also needs much more thought than a simple monolithic approach to data architecture. (David Dawson)
This is where different opinions begin to collide...
On one side, people argue that it doesn’t matter what technology and programing language you use.
“Almost every problem can be solved with any technology. Others spend too much time finding the right technology but if you do it in an iterative way, you have time to think it through and see it in action. This way, bad decisions can be mitigated.” - Andras Fincza, VP of Engineering at Emarsys
Spending a lot of time on selecting the best technology isn’t worth it since the differences are minor.
“The importance of selecting a technology is too overvalued. If the running costs are important, then it can be acceptable but it doesn’t matter that much for us.” - Andras Fincza, VP of Engineering at Emarsys
“If it is a greenfield project, then I use the language my programmers know the most. If it is not a greenfield project, then I use the language that has the best coverage on client side for the business entities in the system.” - Viktor Tusa, DevOps Engineer at LogMeIn
“The good thing about microservice is its encapsulated in a microservice as long as you give an external microservice interface to talk to that thing. I don’t really care as long as they have an interface.” - Steven McCord, Founder and CTO at ICX Media
Selecting the appropriate technology isn’t just a technological question but also a hiring decision.
If you choose a microservice architecture with 10 different programing languages, you need to make sure your team is able to handle that.
“I wouldn't recommend mixing too many programming languages because hiring people gets more difficult. Also, the context switches for your programmers would slow down development.” - Robert Aistleitner, VP of Engineering at Usersnap
“You have to make a conscious choice of what type of development team you want to build. If you want to use many different programming languages, you need to build a dynamic team that’s able to use and learn different programming languages.” - Steven McCord, Founder and CTO at ICX Media
“I highly recommend to use managed services such as AppEngine in the Google Cloud Platform. It will take a lot of the burden from your shoulders. Also, when selecting language/technology/framework it’s always important to select the appropriate one for that specific microservice use case, don’t force a something just because you’re familiar with it.”- Csaba Kassai, Lead Developer at Doctusoft
From Brujo Benavides
On the other hand, some tech leaders were happy to recommend some technologies that could be a good fit for a microservice that serves a specific role.
When selecting a technology for a microservice, it’s recommended to consider:
Some examples of frameworks/ technologies Brujo’s team uses for microservices:
👉 Recommended reading: Technology selection case study for cloud-based apps
When selecting a programing language/technology for your microservice, there are many things you need to consider.
One of the most important thing is to see what competencies your developers have and how big support (tools, community...) is behind a language/technology. According to my experience, companies tend to select a programming language according to the competencies its developers have." - Csaba Kassai, Lead Developer at Doctusoft
“Another factor may be what libraries exist for a language that could be used to speed the project up. Your ideal choice of language may not have libraries for certain things that you may have to invent yourself, which could be another time drain. Obviously, things like fault-tolerance and scalability should be a big factor too. If you’re going to have to re-write something from scratch a few months from now because the initial choice can’t scale, then you might be better off biting the bullet earlier. I think it all comes down to a specific teams situation and the investments they are willing to make.” - Greg Neiheisel, Co-Founder & CTO at Astronomer
At Emarsys, if they want to apply a new programming language, developers need to provide real, logical reasons and consult with lead developers. The team gathers together and discusses the pros and cons of a technology.
They always create a spike solution with different technologies. This lets them experiment with the boundaries of a given technology and see if it can be applied for a given microservice. This is perfect for uncovering the limitations of a technology.
As a big data and analytics company, we deal with very large-scale challenges, which increase the risk and impact of choosing the wrong technology. A single threaded framework, such as NodeJS, while great for network bound services, will not scale when dealing with real-time intensive data processing.
Engineers determine which technology to use by balancing between the tactical and strategic needs and by looking at both the technical and organizational constraints. Are we in a rapid prototyping phase? Does the service deal with large amounts of data? Do we want to add a new technology to our stack because we believe in its ecosystem or do we use existing technologies we have already mastered? Do we want to experiment? Can we find engineers who are passionate about it? Are we willing to commit to this technology in the long term? The ecosystem of a technology is a major factor. We want to engage with the open source community and rather use and contribute to existing frameworks than reinvent the wheel.
In general, we don’t want to be spread too thin; otherwise, you don’t gain the expertise.
Defining clear guidelines, even a checklist, can help facilitate a healthy decision-making process and narrow down the possible technological options to select the one that’s probably the best fit for your team and for the product.
From a data architecture point of view, you need something that can provide data you can easily synchronise into some consistently usable state across a network between services. There are a variety of approaches for that, which is what I’m actually looking for in my microservice deployments. So, you can observe the various frameworks and technologies for implementing these kinds of patterns (this is where techs such as Kafka, Spring Data Flow, Akka and friends sit).
Once we have decided on these patterns and approaches, you then mesh that with what resources you have available. If you have decided on a data flow approach with lots of reactive programming, and you already have Java devs, then it makes sense to pick Spring, Spring Cloud Data Flow, and Kafka and probably to deploy onto some form of Cloud Foundry (if you can get it!).
When it comes to switching to a microservice architecture, there are many challenges.
Before you start transforming your system into microservices, make sure to have real reasons why you want to do it. Going through the advantages and disadvantages could be a big help. Instead of following the latest hype, you need to consider the unique features of your system first and only change the part of the system that hurts the most. Starting with a microservice architecture from scratch isn’t recommended since clearly defining the boundaries of a microservice at the beginning is difficult.
If you decide to switch to a microservice architecture, take an incremental approach and take out a small, non-critical part of your system to see how it works. This also serves as a good way to get organizational buy-in for creating more microservices.
There is no one best way to select the perfect technology for a microservice. Every technology-related decision is influenced by your team’s current knowledge and also by the company’s future hiring plans. In some cases, selecting a technology for a microservice is more of a hiring decision, and it’s up to you what kind of developer team you want to build in the future.
🍔 Hungry for more?