(Part II) Importance of Adaptability in Cloud Software Architecture
By Sathya Srinivasan, Senior Staff Software Engineer
Recap of part one
In part one of this article we discussed the importance of adaptability in the cloud software architecture and the challenges in achieving the same. In this article, we will discuss the several architectural principles that will help us overcome the challenges.
Architectural Principles for Adaptability
To make the cloud software architecture well adaptable to the future demands and requirements, the architecture must break itself down into several pieces — it will let the individual modules develop and grow independently.
The “Microservices Architecture” paves a guided path. It’s an architectural pattern that constructs a cloud application as a set of tiny services that are loosely coupled, independently deployable, and easily maintainable by smaller teams. However, the architecture must ensure it will not overdo (too many microservices) or underdo (too few).
To determine the right boundary to spin off a new microservice, the architecture must follow these principles.
Single-responsibility principle (SRP)
This strategy applies object-oriented design’s single-responsibility principle at the microservice level.
“A microservice should have one and only one reason to change, meaning that a microservice should have only one job.”
A microservice should not own more than one functional storage cluster. If a microservice ends up managing several functional clusters, its responsibilities are being overloaded. While the overloading helps to cut costs, it is not going to make the microservices adaptable and scalable.
Similarly, any microservice that involves CRUD (create, read, update, delete) operations to any destination, for example, another microservice, storage, and so on, can apply this strategy.
The downsides of meticulously applying SRP to every microservice are: increased TCO (Total Cost of Ownership), increased operational overhead, increased team size for development and maintenance, and so forth. There has to be a balance. One way to balance this is by starting with a few microservices in the beginning of the product development, and as more features are added, split those microservices further.
Loose coupling across microservices
Keep the interaction across microservices much less cohesive. The design and implementation of a microservice must depend on the request/response contract defined between itself and each of its downstream microservices. It must not depend on the internal design of those downstream microservices. Even if all the microservices in the dependency chain are owned by the single team, this strategy must be religiously applied. This allows the redesign of one microservice (while maintaining the existing request/response contract) to not affect the other microservices in the dependency chain. This helps with quick TTM (Time To Market), lower TCO, etc.
Modules isolation within a microservice
Within each microservice the module level segregation must be done. It may seem obvious, but it is largely overlooked. The interaction within modules must be more cohesive but across modules must be less cohesive. When a microservice ends up having many modules, it’s the right time to split it into one or more microservices. We must apply the SRP at module level on a lighter side.
Growing traffic
To support growing traffic, a simple question to ask is, “If the traffic my microservice serves today, grows by 10x or 100x, what factors of my architecture must I revisit?”. A few aspects to consider are: operational overhead, volume of tracing generated (such as logs or metrics), health monitoring difficulties, time to find the root cause of the issues in production, and so on. Being aware of these dimensions sets the stage for the architecture to position itself accordingly.
Deployment frequency
Deployment Frequency is an important metric for a microservice. When active development is going on for new features, if a microservice involves changes and needs deployment in almost every release (weekly or whatever cadence the company follows), it falls in the firing line. Then its architecture, modularization, decomposition, and other aspects must be revisited. There may be a possibility of breaking it down. If a microservice continues to grow, adding many functionalities, it would start violating SRP.
TCO versus SRP
There’s always a tug of war between TCO versus SRP. The stance the business leadership takes would play a big role. Depending on the revenue, profit, scale, SLA promise, and other factors, the business leadership may want to keep the TCO at a certain level. The level of control (stringent versus lenient) gives the appropriate freedom for the architecture to apply SRP to the various microservices. Therefore, even though spawning “n” number of microservices is the right thing to do from the architecture standpoint, business leadership goals must be aligned as well.
Most of the cloud platform providers allow scalable provisioning for the underlying hardware resources consumed by the cloud software applications. They must be provisioned effectively to balance between performance and availability versus TCO.
Summary
There is no single hammer for all the nails. If the cloud software and its architecture have to survive across growing demands and functional requirements over a period of many years, adaptability is the key. Being aware of the several challenges discussed and aligning the cloud software architecture towards the architectural strategies will help in guiding the software architecture to be adaptable and maintainable, while continuously meeting the growing business demands and requirements.