Microservices Architecture: The Good, The Bad, and What You Could Be Doing Better


It’s no longer one app to rule them all. From a user experience perspective, the industry has reached what Web Informant David Strom calls a “cheaper, pay by the drink model, [where you] don’t have to implement a particular computing environment or end-point device–now it’s their phone or their tablets.” On the consumer side, we aren’t just offering behemoth platforms like Salesforce, but we are drilling down to add dimension, allowing users to pick and choose their workflows. More and more, consumers are demanding these “microapps” or “apps of record.”

On the backend, a similar trend is happening with developers and the software architecture design pattern commonly called microservices, where complex applications are composed of small, independent processes and services, each organized around individual capabilities. These microservices communicate with each other via language-agnostic application performance interfaces or APIs. Reflecting the consumer trend, these services are small and focus on completing singular tasks.

This white paper works to identify what microservices are, when the strategy works, and when it simply does not. We’ll also offer methods of working around five common barriers to microservice architecture.

No Longer One App to Rule the World

“Back in the day — and actually still today — most systems started as a monolithic system, which basically means the entire application exists in a single code base and is deployed and, importantly, scaled as a single unit,” said Tammer Saleh, director of product for Pivotal Cloud Foundry Services, during his talk at the 2014 Nordic APIs Platform Summit in Stockholm. Usually used in enterprise applications, a monolith is a single executable action on the service-side application. These monolithic apps built as single units have been the prevailing architectural style for some time now.

Eschewing former norms, Cloud Foundry now joins Amazon, Netflix and The Guardian in making up the first wave of corporate deployment of microservices architecture.

Figure 1: Monoliths And Microservices. Courtesy of James Lewis and Martin Fowler

Figure 1: Monoliths And Microservices. Courtesy of James Lewis and Martin Fowler

Why would people pivot away from these monolithic apps built as single units? Well, like governments, the more disconnected, autonomous layers built into one purpose, the more rigid, unyielding, and unchanging the process can be, increasing the chance of entire system collapse due to a small problem. A monolithic application is also harder to scale, as one small change must be deployed across all processes.

What is a Microservice?

Software developer advocates James Lewis and Martin Fowler gave the best definition we could find for this increasingly popular architectural pattern:

“The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.”

While microservices is still more of a concept than a predefined architecture with specific requirements, Lewis and Fowler say there are certain attributes that typically come with microservices, including:

  • Componentization as a Service: bringing certain components together to make a customized service.
  • Organized Around Business Capabilities: segregating capabilities for specific business areas like user interface and external integrations.
  • Development Process is Based on Products Not Projects: following Amazon’s “eat your own dog food,” developers stay with the software for the product’s lifetime.
  • Smart Endpoints and Dumb Pipes: each microservice is as decoupled as possible with its own domain logic.
  • Decentralized Governance: enabling developer choice to build on preferred languages for each component.
  • Decentralized Data Management: having each microservice label and handle data differently.
  • Infrastructure Automation: including automated deployment up the pipeline.
  • Design for Failure: meaning that more ongoing testing of “what if” has to occur to prepare for failure.

Where Do Microservices Win?

As we move into a more specialized world and user experience, microservices, in some ways, make for a better developer experience too, which allows you to grow your business more rapidly.

More and more people are flocking to try the microservices architecture because its modularity of small, focused, quasi-independent services allow businesses to deploy and scale services more easily. This segmentation also allows smaller teams that create smaller code bases.

Microservices also lend themselves to agile, scrum and continuous delivery software development processes with shorter lifecycles. This architecture distinguishes itself from service-oriented architecture (SOA) because each microservice only belongs to one application, not multiple.

Where Do Microservices Go Amiss and What Can You Do?

Since they are inherently individual, microservices bring with them their own set of new issues. Microservices often experience compatibility issues, as they are built by different teams on top of different technologies. This can all lead to an unstable environment where people are building in different directions. To relate these parts, extensive workarounds may be required, which may actually take longer to fix than if they were built in a monolith environment.

Thankfully, there are ways to deal with these problems. Here we cite the experts on their ways to overcome the five most common hurdles to using microservices:

Microservice Challenge #1: Building Microservices First

Over-eager developers, ready to push themselves to market, may start out by first building a microservice and find that it becomes too complex and hard to develop, ultimately making the app unscalable.

“Being boring is really good. You can scale a lot with being boring,” Saleh said. “When you move to a microservices architecture, it comes with this constant tax on your development cycle that’s going to slow you down from that point on,” like any complexity will do.

With this in mind, Saleh argues that people should still start with that behemoth app and then extract information into the smaller microservices once the app is stable.

Of course, with microservices, individual pieces should have minimal communication with each other, which is where he suggests creating a gatekeeper so only one service can contact the database schema at a time. But this brings its own set of problems when the services and the APIs they are communicating with each have their own language, which can lead to lock-step deployment, downtime, and worry of a complete crash upon redeployment.

Saleh offers what he calls the rather painful solution of semantic versioning guidelines to allow for continual deployment. French front-end developer Hugo Giraudel offers the best explanation of SemVer, a three-component system as follows:

  • X represents a Major Version, for anything that will probably break the existing API
  • Y represents a Minor Version, for implementing a new feature in a backward-compatible way
  • Z represents a Patch, for fixing bugs

The system helps you clarify the release of the API or microservice as X.Y.Z, making version 2.1.0 a much larger change than 1.1.9, which would be allotted for bug fixes. This allows you to catalog versions, identify patches, and help guide your team’s major and minor version releases.

Saleh admits record-keeping can be tedious, but “this is part of the inherent pain of building a microservices architecture. What you get out of this is you can scale your engineering team larger [and] you can scale your application much more easily.”

Microservice Challenge #2: Information Barriers to Productivity

As software manager Richard Clayton wrote about his team’s experience, microservices can put up artificial barriers to productivity. “We decided to split the backend into eight separate services, and made the bad decision of assigning services to people. This reinforced the notion of ownership of specific services by developers. Because services were owned by people, developers began complaining of Service A being blocked by tasks on Service B,” he says. “This lack of concern became a very bad habit; we stopped trying to understand what our peers were doing even though we were responsible for reviewing their pull requests… Developers lost sight of system goals in favor of their individual services’ goals.”

Clayton also says that, while microservices are meant to be built and scaled independently, there’s a strong desire to share code. “You can either replicate functionality across services and increase the maintenance burden, or you need to carefully construct shared libraries and deal with dependency conflicts that may arise.”

Similarly, Selah mentions that though microservices enable unique technology customized to each element, the operational hazards of incongruent parts can increase the potential for system failures, causing strain on a team that isn’t ready to be ripped apart by new architecture.

How can your team overcome this? Well, Clayton argues that microservices shouldn’t be the de-facto architecture. If your team already has communication issues, it’s a sure way to fail. He also follows Saleh’s advice in recommending that any microservice must be kept simple, consciously avoiding the natural habit of going granular from the start. And he recommends that you build your microservice on top of a Platform as a Service (PaaS) which will enable better communication among microservices, at least on the back end.

Microservice Challenge #3: How Do Your Services Find Each Other?

You are building, deploying, scaling and evolving each of these business capabilities separately, but they need to be able to communicate with each other in order to create logical workflows and a complete finished product that, from an end-user perspective, is indistinguishable from the monolithic app.

Saleh says that most often developers try to hard code the locations into the source code, but a change to the location of your services requires changes in your code base, which leads to a string of other problems.

What is a better way to overcome these challenges in order for one microservice to find another? You have two options: service discovery protocol or a centralized router. Both require registration and deregistration, as well as high availability and scalability. From there, it’s up to you to decide which fits your development lifecycle.

Service discovery allows for an automatic detection of services offered and directs one service toward the other, as the router works between the systems. While the service discovery tells you where things are, the centralized router is actually proxying all the traffic. The router is built very transparently and exposed externally, but is much more challenging to build than the discovery service, where you don’t need to route all the data.

Microservice Challenge #4: How Can Services Communicate with Each Other?

Since each part works independently, there is the risk of latency when each piece is brought together. While the whole point of microservices is that they are able to work independently, they need to work together, which can be a repeated challenge. Particularly when many services are making calls to many others, you can have a “dogpile” of information — when one service goes down while the other connecting services don’t have any time-out mechanisms, eventually the entire app will collapse.

Saleh says you can create a circuit breaker which acts like a discovery service, where one microservice realizes another is “sick” and notifies the main circuit breaker. From that point on, a microservice will be able to check the service discovery to determine if the microservice it is connected to is broken in order to prevent calls being made to or from said microservice. Saleh recommends setting a “time out” for about ten minutes.

Microservice Challenge #5: Decentralized Data Isn’t Always a Positive

Having decentralized data management sees two sides to the same coin — it allows for teams to work independently and for the app to scale more quickly, but how each team quantifies things can become garbled. As Lewis and Fowler put it, “It means that the conceptual model of the world will differ between systems. This is a common issue when integrating across a large enterprise — the ‘sales view’ of a customer will differ from the ‘support view.’ Some things that are called ‘customers’ in the ‘sales view’ may not appear at all in the ‘support view’.” When data is managed separately, semantics could truly make or break an update.”

According to Lewis and Fowler, a good way to overcome this hurdle — which resides among microservices and with external APIs — is through domain-driven design. DDD divides and re-bundles complex domains into multiple bounded contexts, which then maps out the relationship between them.

You can also choose to manage inconsistencies by using transactions which test the integrity of the interactions before releasing an update. However, distributed transactions are notoriously difficult to implement.

Lewis and Fowler say that none of these fixes are perfect, but “the trade-off is worth it as long as the cost of fixing mistakes is less than the cost of lost business under greater consistency.”

In Conclusion: Are Microservices Right for Your App and Team?

Let’s sum up the benefits and drawbacks of using a microservices architecture instead of the more common monolithic kind. Then, we’ll let you decide which is right for your app and your team:

How does a microservice outshine a monolith?

  1. It makes your app more scalable with smaller teams.
  2. Enables modularity and is more open to change in general.
  3. Uses a smaller codebase.

What are microservice architecture’s limitations?

  1. It can cause communication problems among different parts of the app and within your team.
  2. It requires increased effort later on to catalog, test, and fix incompatibilities.
  3. You should still build the monolith before building the microservices on top of it.

For more, watch Tammer Saleh of Pivotal Software give a talk on microservices architecture.

Now tell us your experience. Have you experimented with microservices yet? How did your team react to the restructuring? Was your app more or less stable? Tell us your story below!