The last five years have seen a shift in software development practices. In 2010, companies almost universally built their applications as large monolithic services and deployed them to virtual machines. In 2015, many of the same companies are now building microservices and deploying them to containers.
The companies that have moved to microservices are reporting significant benefits, including faster release cycles, easier scalability, and better fault isolation. These benefits are driving forward an industry-wide shift from monoliths to microservices.
But we’re also hearing reports of pain from those who have tried or are trying to adopt microservices. They find themselves dealing with issues such as the complexity of distributed systems, increased operational overhead, and higher hardware costs.
This has led to a chorus of voices claiming that the benefits of microservices don’t outweigh the costs. In this essay I will present my take on the situation: I think that the current backlash against microservices is valid and important – but it’s not telling us what we should do next. Instead, I think we need to re-evaluate how we build large software systems, regardless of whether they’re monoliths or microservices – or anything else for that matter!
The biggest question everyone wants to know is: “Is using microservices better than using monoliths?” I don’t have an answer to that. The only honest response is it depends.
The impact of using microservices will be different for each company, and it really depends on the company culture, the skill of the team, and many other factors. What we’ve learned at SoundCloud is that you need to develop a good understanding of your application architecture and know when something needs to be changed. You should constantly evaluate your options and choose what’s best for you at the current point in time. No one knows how your application will grow, so you need to be able to change things if required.
I’ve outlined some points below that I believe are important to keep in mind when thinking about whether or not you should use microservices:
The problem with microservices is that it can be a pain to make the separate components work together.
In practice, we often find it useful to have a layer of shared code between our services, which we call a platform.
Our platform contains code that used to be part of our monolith, but which we’ve repurposed as shared functionality.
So we’ve gone from a monolith containing all our code and data, to microservices that share nothing, to microservices that share some things via a platform. This trend is generally for the better, but it’s not always clear where the limit lies.
The data is clear: microservices are an improvement over monoliths. But they’re not obviously better. The data says they’re better, but it doesn’t say how much better. It would be nice if we had more evidence to go on.
One thing you could do is look at other kinds of applications that have been redesigned to take advantage of the possibilities of their medium.
In architecture, for example, modernism was a reaction against classicism. A neoclassical building tries to copy the styles of ancient Greece and Rome. The acme of neoclassicism was the Beaux Arts style of the late 19th century, which culminated in buildings like Grand Central Station (now landmarked) and Pennsylvania Station (now demolished). When the modernists came along—led by people like Mies van der Rohe and Le Corbusier—they rebelled against this aesthetic. They created a new aesthetic in its place, using steel and concrete as building materials rather than stone and brick, and paying more attention to function than form.
The modernists copied no one. This was where they really broke with the past. Classicism wasn’t just a visual style; it was part of a larger program trying to emulate Classical antiquity in all fields of human endeavor
I’ve been a developer for over 15 years, and have been using AWS for about 5. In that time, I’ve seen large monolithic applications get replaced with microservices and small utilities.
The smaller services had some benefits:
Each service could be written in just the right tool for the job.
No need to redeploy the entire application when only one service is changed.
Smaller deployments mean less risk.
But there were also downsides:
It was harder to test changes that involved multiple services at once.
There were more moving parts to keep track of.
It was harder to visualize data flow when tracing through logs, especially if the logs were spread out across many different systems.
More moving parts means more failure points.
I’m on a mission to help more companies get better at building software. It’s a big job; there are a lot of companies out there, and only a small fraction of them is currently good at it. And I’m not just talking about startups: enterprises are also part of the problem, and they have more resources to throw at it than startups do.
I’m not alone in this mission either; there are hundreds of people working in the same field. But I am unusual in that I don’t think that software is mostly about coding. When I talk to developers I find myself saying things like “no, you should spend most of your time thinking, not coding,” or “no, you shouldn’t keep adding features, you should try to understand what’s really going on.”
Most programmers work for companies that use monolithic architecture. Each company has its own monolith–its own giant codebase that takes hours to compile and deploy and requires extensive coordination between teams. These massive applications tend to be difficult to understand, hard to work with, and even harder to change. For example, it might take an entire day for developers at Microsoft or Google to deploy changes from their desktops into production.
Microservices are about engineering for agility. The microservice community has done a good job of identifying many techniques and practices that can help you achieve that goal, and the twelve-factor app is a good basic pattern to get you started. But there are no silver bullets. Any microservices initiative will be a long journey.
Along the way, some of the practices will fail to live up to their promise, or will turn out to be impractical for your organization for one reason or another. Others will prove difficult to adopt quickly enough, or at all in some cases, because of legacy systems and technical debt. When you encounter setbacks like these, I hope that you’ll remember the three goals of software development:
Make what we want
Make it work
Make it right