You’re sitting on hundreds of thousands of lines of legacy C++. Oh, who are we trying to kid? It’s millions of lines of Vectran, a short-lived Fortran variant created by IBM in the 1970s. But, hey, if it ain’t broke, right? Except it is broken. Any time someone tries to add a feature, the thing breaks. Even trying to fix bugs creates more bugs. But if you just don’t touch it, it keeps on working.
The problem is that innovation demands agility and velocity. All the cool companies that never had to worry about Y2K are outpacing your clunky old legacy software. Investors are demanding the next big thing. Customers are jumping ship in droves.
The answer is to kill your application monoliths, and not create any more new ones. The way to do that is by using microservices architecture, a technique that breaks large applications into lightweight apps that can be scaled horizontally.
Microservices segment functionality into separate applications that are loosely coupled by RESTful APIs. For example, eBay created separate Java servlet applications that handled users, items, accounts, feedback, transactions, and more than 70 other elements back in 2006. Each of those logical functional applications is a microservice.
Each microservice is self-contained. Microservices do not share a data layer. Each one has its own database and load balancer. Isolation is a critical component of microservices architecture. Individual microservices require different scaling techniques. For example, some microservices might use relational databases whereas others might use NoSQL databases.
The benefits of microservices
Microservices architecture tears down large monolithic applications with massive complex internal architectures into smaller, independently scalable applications. Each microservice is small and less complex to develop, update, and deploy.
When you think about it, why should those functionalities need to be built into a single application in the first place? In theory, at least, you can imagine they live in separate application and data silos without major problems. For example, if the average auction received two bids, but only a quarter of all sales received feedback, the bidding service would be at least eight times as active as the feedback application at any time of day. If these were combined into a single application, you end up running—and updating—more code than you need more often. The bottom line: Separating different functionality groups into separate applications makes intuitive sense.
Also, when you architect around microservices architecture, you gain nonobvious benefits, such as tying in with other new technologies such as PaaS, Docker, and Linux containers.
Building applications the microservices way not only makes your applications more flexible and scalable. It increases the scalability of teams building applications. With monolithic code, you have one big team of people working on one big piece of code—and stepping on each other’s feet all the time. The speed of development slows exponentially with the growth of the code monolith.
But with microservices architecture, apps are built by small, decentralized development teams that work and change microservices independently. This makes it easier to upgrade services and add functionality. Both the software and the development process become more agile.
The challenges of microservices
But every architecture has both strengths and weaknesses. Even with its clear benefits, microservices architectures bring a whole new set of problems that are hard to tackle—particularly around logging, monitoring, testing, and debugging your newly decentralized, loosely coupled application.
If there’s a bug, which microservice is responsible for it? The interdependencies among microservices can make that question maddeningly hard to answer. Microservices communicate with each other, generally through lightweight JSON REST APIs. Unlike their predecessors XML-RPC and SOAP, REST interfaces tend to be more loosely defined. These lighter-weight APIs are more flexible and easier to extend, but they also add a new interface that needs monitoring and may break or cause bugs.
With monolithic applications, you can add debugging hooks in the code and logically step through every execution layer to discover the problem areas. When you are dealing with a mesh of dozens or even hundreds of separate microservices talking to each other with loosely defined APIs, you lose that luxury.
Nonetheless, with careful planning you can overcome these difficulties. There are debugging tools that can help, but you will likely have to stitch together your own solutions based on other, partial situations out there.
How microservices relate to containers and PaaS
There is a common misconception that to use microservices you need to use PaaS or Linux containers. It’s simply not true. You can use PaaS and Linux containers without microservices, and you can use microservices without PaaS or Linux containers. Neither requires the other.
But they do complement each other well. PaaS environments, whether in the form of public clouds such as Heroku or private clouds such as Cloud Foundry and OpenShift, optimize for running many smaller applications. Porting a 3.3-million-line C++ application to a PaaS platform will never happen.
If you deconstruct your application into smaller, bite-sized applications that self-contained and scale independently, those bite-sized applications often end up being good candidates for a PaaS environment.
Likewise, Linux containers are better suited for small, stateless applications like microservices than large monolithic ones.
After all, one of the biggest and most obvious differences between a virtual machine and a Linux container is the lack of state. Virtual machines can be configured to keep their state, whereas the architecture of Linux containers intrinsically throws out any differences from the base image. You can mount stateful folders in Linux containers, but the container itself won’t change unless you commit the change.
The horizontal scaling philosophy of microservices architecture promotes the concept of share-nothing, stateless applications. They do not store or modify the underlying file system. That’s why why people conflate microservices with Linux containers: Neither retains its state.
How microservices relate to SOA
Microservices are kissing cousins to SOA (services-oriented architecture), but there are significant differences. On the surface, SOA is associated with SOAP and XML-RPC whereas microservices are associated with JSON. But in some ways, the associated API format is more a cosmetic difference.
Likewise, SOA uses enterprise service buses whereas microservices use lighter-weight pub-sub service buses. Again, the principle is similar, though lighter-weight.
The biggest difference between microservices architecture and SOA is that microservices must be independently deployable whereas SOA services are often implemented in deployment monoliths.
Are microservices right for you?
It’s important to remember that microservices are a response to hitting a glass ceiling. At some point, traditional monolithic application architectures don’t scale any more. This happens to every successful software project. The database grows too large, or there are too many millions of lines of code, or you simply can’t add features quickly enough any longer.
If you have not hit a glass ceiling yet—that is, if your legacy application is still working well and doesn’t need to be changed much—then adopting microservices for their own sake will gain you very little.
After all, microservices bring quirks and difficulties to the development process. Keeping all of these new services running can sometimes feel like juggling a dozen balls in the air. Adopting declarative orchestration tools such as Kubernetes can take some adjustment as well. Complex microservices architectures have their own lexicon to cover all the new software patterns you will need to adopt.
Yet microservices aren’t nearly as daunting as SOA used to be. In fact, microservices practices can be implemented in even the smallest software projects—and you don’t need to throw away all your old code to get started.
If you have a large application that is getting out of hand, with software life cycles that take too long and a pace of innovation that has ground to a standstill, microservices might be just the thing you need. Alternatively, if you are just starting out, it would be smart to consider building a microservices-based application from the beginning.
eBay has said that microservices architecture has enabled it to expand to massive scale, increased code scalability and maintainability, spurred rapid business innovation, created faster product delivery, and even enhanced security. Google, Amazon, Twitter, PayPal, and Netflix have all had similar experiences. Many of these companies have also created public tools to make adopting microservices easier.
Whether you are suffering from the problems of maintaining legacy code and don’t know how to move forward, or you are starting out with a brand-new greenfield application, now is a good time to evaluate a microservices approach to application development.