As an application developer or software designer, what we want is to develop or build software that’s responsive to changes. There is much pressure in terms of request from various sources and these can be external or internal forces not limited to market demands, growth, new requirements, bugs, defects, new clients and so on. Idyllically, we can respond to these loads at a balanced rate and with assurance. To be able to build such a resilient platform, the development approach should change to the techniques that are fault-tolerant, dynamically scalable and can stand or resist the friction and pressures.
We might already have in place a monolithic application or software and we want to remove any bottlenecks to develop as time goes by and the system evolves. We want to be able to quickly and seamlessly replace any of its components and break it down to smaller services. We want to have autonomous teams that are responsible for small services as a part of a larger system. We will also want those teams to coexist without the need for constant synchronization and without blocking other teams. For that, we need to think about microservices architecture.
With a monolithic application, our primary deliverable is a single top to bottom application. This application is split horizontally into different technical tiers or layers, for instance, a typical 3-tier application that consists of data, logic and presentation; and vertically into different business domains.
Configurations like Model-View-Controller (MVC) and frameworks like Spring, Django reflect imitate the 3-tier model. Each tier provides services to the tier above: the data tier provides persistent state; the logic tier executes useful work by providing services, and the presentation layer presents the results back to the end-user or the requester.
Each microservice is similar to a monolith in the sense that it has its data layer, performs some business logic and returns the result and outcomes to consumers through APIs. Every microservice in the system has its own business or technical capability to interact with other microservices to execute work.
In a monolithic application, your architecture is limited to the boundaries of the application itself. In a microservice application, we’ll be planning for something that’ll keep evolving both in size and breadth.
Let’s think of it as a city: building a monolith is like building a skyscraper; whereas building a microservice application is like building a neighbourhood: we’ll need to build infrastructure (plumbing, roads, cables) and plan for growth (zone for small businesses versus houses). This analogy highlights the importance of considering not only the components themselves, but also the way they connect, where they’re placed, and how we can build them concurrently. We want our plan to encourage growth along good lines, rather than dictate or enforce a certain structure on our overall application.
Most importantly, we don’t run microservices in isolation; each microservice lives in an environment that enables us to build, deploy, and run it, in concert with other microservices. Our application architecture should encompass that whole environment.