Advantages and disadvantages of the most common software architecture patterns
- A monolithic application is a software application compiled into a single executable, usually stored in a single source control repository.
- Microservice architectures include a series of independently developed and deployable services, stored in separate source control repositories or a mono repo.
- Even though they may be seen as “uncool”, monolithic architectures are the best place to start when developing a new system or in a small organization.
Since microservices architectures entered the scene and become popular in the early 2010s, there’s been an ongoing debate about whether they are better than traditional monolithic architecture patterns. Big tech companies like Netflix, Amazon, Spotify, eBay and Uber have switched to microservices, but does that mean you should too? Let’s explore some of the advantages and disadvantages of monolithic vs. microservice architectures.
A monolithic application is a software application compiled into a single executable, usually stored in a single source control repository. Traditionally, most applications were developed as monoliths, but today it’s seen as a way to quickly get up and running with a simple codebase in the early days of launching a new product. Even though they may be seen as “uncool”, monolithic architectures are the best place to start when developing a new system or in an organization that’s still relatively small.
Monoliths consist of a 3 tier architecture, which includes the following:
- A client-side user interface consisting of HTML/JS/CSS pages.
- A server-side application that handles HTTP requests from the client and executes queries in the database.
- A database consisting of tables or documents for storing and retrieving data.
- A simple codebase that’s easy to work on. Modular codebases inside monolithic applications are quick to set up and easy for developers to reason about. The whole app is compiled into a single executable, making it easy to access data and functions without worrying about inter-process communication.
- Quick to deploy with fewer security concerns. Setting up your continuous integration and delivery pipeline is much simpler for a monolithic application, as there is only one executable and one service to deploy. It’s far easier to make security considerations as there are fewer services that could be compromised, with less sensitive data flowing through the network.
- Lower network latency for requests. All requests are handled by one process, which reduces latency as fewer calls are happening in the backend. There may only be one request made to the database rather than waiting for other services to complete tasks.
- They become slow and difficult to manage as the codebase increases. As the codebase increases, the benefits provided by monolithic architectures reduce. Application boot time increases, and managing the large codebase becomes problematic, requiring refactoring and modularization to keep it organized and maintainable.
- Scaling horizontally becomes a challenge as the load increases. Monolithic applications are typically scaled vertically by adding CPU and memory to serve more concurrent requests. Scaling monolithic applications horizontally (adding identical instances) is inefficient, making it difficult to scale them beyond a certain threshold.
- Difficult to adopt and test new technologies. Switching programming languages or frameworks requires rewriting the entire monolithic application, which may be impossible due to time or funding limitations. This makes it difficult to test new technologies without spending a lot of effort on transitioning to them.
Microservice architectures include a series of independently developed and deployable services. They are loosely coupled with separate responsibilities and concerns. Each microservice can have a dedicated source control repository or be part of a larger mono repo. This type of architecture is more appropriate for mature products running at a larger scale or in organizations with many teams and developers.
The biggest consideration for these architectures is how the services interact with each other to fulfill an end-to-end user request. An event bus such as RabbitMQ or Kafka is often used as a communication layer between lots of services. Each microservice usually defines an API specification that describes how it can be interacted with by other services.
- Teams can own services and move at different velocities. The clean separation of concerns with microservices allows teams to own and work on services independently and asynchronously. This works great in larger organizations where teams may want a faster or slower release cadence depending on the project.
- Multiple languages and frameworks can be used. Polyglot architectures allow teams to choose their own programming languages and technologies. This means they can select the best tool for the job rather than being constrained by languages that have been used in the past.
- Services can handle a large number of requests with horizontal scaling. Microservices can autoscale horizontally once they have been made stateless, allowing them to handle much higher request volume at a lower cost. This also makes them more resilient to errors, as new instances can easily be launched.
- Making changes across multiple services is complex. When making a change you must consider the impact it will have on all the upstream and downstream services involved. This makes it much harder to reason about the knock-on effects your change may have on related services.
- Database transactions across many services are difficult. Database transactions are commonly used in systems to ensure data integrity when editing multiple pieces of data at once. This becomes challenging with distributed systems, and the solution often involves switching to an eventually consistent model, which is more complex to implement.
- Debugging and testing services can be challenging. Debugging a request from an end-user becomes increasingly complex the more touchpoints it has with various backend services. Distributed tracing is required to understand the flow of messages through your microservice architecture.
As with most things in software, there is no right or wrong answer here. Make sure to weigh the pros, cons and compromises for either approach to make the best decision. Consider the company stage and product stage you’re at and have a plan if you hope to switch from a monolithic to a microservice architecture.
Leave a comment if you have any extra points to add!
Stay chill 🧊