Pros and cons of microservices architecture

Cons

Microservices bring many problems that do not exist in monolithic applications or are much easier to solve. What challenges will you have?

  • Data consistency is difficult to achieve. Distributed transactions result in poor performance. The trade-off is eventual consistency but asynchronous communications is often not easy to accept
  • Error handling becomes more complicated because of distributed nature of the system. Failure in one service may require to trigger undo operation in another service
  • Synchronous dependencies between services reduce performance and availability. Calling service waits until called service will do its stuff. In case of synchronous communication SLA of the system is multiplication of its micro services (0.99 SLA in service one x 0.99 SLA in service 2 = 0.9801 SLA of the system composed of 2 services)
  • Remote calls between services are over network, usually HTTP, so data serialization is required what reduces performance
  • Bigger effort must be put into integration tests
  • Fault tolerance needs a lot of attention
  • Fully automated build and release pipelines are a must because of large number of deployment units. Manual management would be too time-consuming and too error-prone
  • Application monitoring, metrics, alerts and self-healing mechanisms must be implemented to successfully manage production environments. It is absolutely counter-productive to manually search logs in tens or hundreds of running application nodes

Pros

Why to take the burden then? When it is beneficial to choose micro-services over monolithic app?

  • Divide and conquer principle. System split into smaller highly independent parts is easier to manage and maintain. It is like splitting large complicated problem into many smaller and easier problems
  • Teams can be smaller and work more independently. Ownership is bigger because teams feel responsible for their parts. In large monolithic app responsibility is often diffused
  • Failures affect smaller parts of the system, other components may be still functional
  • Each system part can be planned, developed and deployed quite independenty.
  • Different parts of the system may use different technology what allows to update technology stack more often and use different tools for different problems
  • Each part of the system can scale independently. It is easier to identify bottlenecks
  • With mature dev ops culture it is easy to spin up a new service and provision new computing resources. It is often much more effective and less risky than modifying existing service
  • Microservices can be a medicine pill for tired teams. Sometimes teams just need to start from the scratch, leave old buggy system aside for a while and do something smaller that they can be proud of and have fun with

Summary

Microservices are technically harder to develop but in some situations it pays off to take that extra effort. This architecture would be a more natural direction for larger organizations with proven business model and mature teams who are committed to devops culture. For smaller products and start-ups which are still discovering their business model the extra burden brought with microservices may not help but be counter-productive.

What drives architecture decisions?

There is no single best architecture that fits all problems. Architecture decisions must be based on business and technical constraints. We often call those constraints as “non-functional requirements”.

What are the example drivers?

  • time – when project has to be delivered? is there a deadline like upcoming changes in law, scheduled event or a business opportunity that exist only for a while?
  • scope – how much there is to be done? is it a small project or long-term investment?
  • skills in the team – what programming languages, frameworks and tools the team is most productive with?
  • scalability – how many users will be using the software? how fast the number of users will grow? will there be any peaks in traffic?
  • performance – are the operations happening in real-time or can be done in background with acceptable delay?
  • security – is there a risk of data breach or system does not deal with private data?
  • maintainability – will the system be developed in long-term? will it be evolving and changing often? should regression tests be automated or it is acceptable to perform manual tests once and codebase will be frozen afterwards?
  • availability – what happens in case of system failure? is the plane crashing so that system has to be up 100% of time, or maybe it is a background data integration and it is acceptable when system will be down for a couple of hours?
  • business process automation – is it required to automate all the steps and cases in the process or it is acceptable to leave some manual work to be done for example by customer care department
  • platform – on which devices will the software be used? Smartphones, laboratory devices, cars, servers, watches, payment terminals or many of them?
  • usability – is it a B2C/C2C software intended to be used by end-consumers or only trained stuff will be using it?
  • already possessed resources – do employees already work on MacBooks and all DevOps tools are built for AWS? Then .NET 4.7 and Azure are not the best choice
  • budget – Last but not least. Are we investing in a product that already brings revenue? How much will we save or earn thanks to that project? Is it a new business idea to validate at lowest possible cost?

It is important to list constraints at the beginning of the project and make it transparent for both stakeholders and development team. Having common awareness of constraints allows to make more confident, accurate and quicker decisions.

It is also important to note that drivers may change when business environment will change. Good architecture will adopt without putting too much effort to prepare for that at early stage. Example: you may built the search functionality based on simple SQL “like” query, but abstract the search functionality so that it is decoupled and will be possible to be replaced by more scalable technology in the future without changing other parts of the system.

When the system has good logical structure it will be much easier to adopt it in the future for larger amount of users, even if the architecture at the beginning is a simple monolithic app. But if the logic is mixed-up since the beginning and code is a mess, no matter what fancy architecture and tools will be used – the project will fail.

Summary

  • Know and communicate your drivers.
  • Estimate how likely it is for each driver to change
  • Have a high-level plan of adopting to likely changes

That rules lead to better decisions when building software.