Monoliths, Microlith, Moduliths, self-contained systems, a system of systems, nano services
Monoliths
I am sure we now have a generation of devs that believe only in microservices and never even see monoliths.
The first thing that came into your mind on Monolith — is the dark ages JSP app that mixes serverside rendering, server logic, and stored procedures on the Database side into one big mess in one single deployment. So it is a main sailing point of microservice world independent deployment and team independence.
SAP has hot reloading modules in 70x that allow deploying independent parts of systems on the fly.
We could apply this to the salesforce platform where code is metadata, so you could modify a system on the go and deploy modules gradually on the fly.
So monoliths allow independent deployment and even independent development in a different repo if needed with a federated application pattern.
Let's discover a better way of doing old monoliths
Modulith
Write Monoliths like a pro
Modulith is a software architecture pattern that balances monolithic and microservices-based architectures. The term “modulith” is a portmanteau of “module” and “monolith,” which highlights its modular approach within a monolithic application.
The main ideas of Modulith can be summarized as follows:
- Modular structure: Moduliths advocate for dividing an application into smaller, cohesive modules based on functionality or domain. Each module represents a specific business concern and is responsible for related functionalities. This approach leads to better maintainability, testability, and separation of concerns.
- Decoupling and encapsulation: Modules in a Modulith are designed to be loosely coupled, meaning that they have minimal dependencies on each other. This allows for easier changes and promotes reusability of code. Encapsulation is also a key principle, where modules hide their internal implementation details from other modules, exposing only well-defined interfaces.
- Internal communication: Unlike microservices, where inter-service communication occurs via network calls, Moduliths use in-process communication. This means that modules can directly invoke methods or access data from other modules without the overhead of network calls, resulting in better performance and simpler communication patterns.
- A Modulith employs a shared infrastructure for common concerns such as data storage, caching, and messaging. This reduces the complexity of managing separate infrastructures for each module, as seen in microservices.
- Evolution path: Moduliths provide a practical evolution path for legacy monolithic applications. They can be gradually refactored into modular structures and if needed, can be split into separate microservices. This offers flexibility in adapting to changing requirements and scaling needs.
InModulith offers a middle ground between monolithic and microservices-based architectures by combining the benefits of modularity, decoupling, and shared infrastructure while maintaining the simplicity of in-process communication. This approach can benefit organizations wishing to evolve their monolithic applications or avoid the operational complexities of a full-blown microservices architecture.
Federated applications and Federated “microservices”
Federated Microservices are the independently deployable components of a federated application. In a federated application, components are loaded from multiple network locations and repositories at runtime. They are not developed by a single team or built from a single codebase. Multiple federated application components can run in a single application instance; and can be redeployed at any time, without restarting the application or interrupting other components that happen to be running.
The idea of a federated microservice or application came from REST principle code on demand. We have used this pattern for ages on the front end. You load and execute code and scripts when needed.
What you need is a smart host that manages and load modules from different sources.
One of these examples is ÆGIS
Self-Contained Systems and System of Systems
Systems is still a modular view of architecture but promotes a self-containing approach. You bundle UI, services, and part of data storage to independent and deployable artifacts. So it is a step back from microservices to aggregated services around a particular domain.
Systems are:
- Autonomous components: Each SCS is an autonomous component encapsulating a specific business domain or functionality. It includes everything needed to provide its functionality, such as UI, backend, data storage, and any required integrations. This autonomy enables easier development, testing, and deployment of individual components without affecting the entire system.
- Decentralized data management: Self-Contained Systems manage their own data storage and are responsible for their specific domain data. This means that each SCS has its own database, and data consistency between systems is handled through asynchronous processes or eventual consistency patterns. This approach reduces the risk of a single point of failure and simplifies data management.
- Strong encapsulation: SCS components enforce strong encapsulation by hiding their internal implementation details and exposing only well-defined APIs or interfaces for communication with other systems. This approach promotes separation of concerns, loose coupling, and modularity.
- Communication: Self-Contained Systems communicate with each other through synchronous (e.g., REST, gRPC) or asynchronous (e.g., message queues, event-driven) protocols. This communication is limited to the necessary level to avoid creating tight coupling between components.
- UI composition: User interfaces in SCS are composed of smaller, reusable UI components that belong to individual systems. This enables a flexible and modular approach to building user interfaces and enhances the autonomy of individual components.
- Independent deployment: Each Self-Contained System can be deployed independently of others, allowing for continuous delivery and scaling components based on their specific requirements. This also enables teams to work on and release individual SCS components without affecting the entire application.
As a result, we build our Application as a System of Systems.
A system of systems (SoS) is a large-scale, complex engineering concept where multiple independent systems or subsystems collaborate to achieve a higher-level objective or functionality. These individual systems maintain their autonomy and have unique purposes and capabilities, but when integrated, they form a more complex, unified system that can deliver functionalities not possible by any single system alone.
Microservice
I hope we all know this pattern and have used it for decades. I only list a few pros and cons there.
Pros
- Independent development (well, as you can see, not unique to microservices)
- Independent deployment — here, still not unique anymore but the isolation level of microservice is much much better than in federated apps
- Independent scalability — for me, one of the key factors if you have application parts with different loads and different critical paths, it is a good choice
- Poliglotic — I have seen a lot of failures in a company that go wild and use different language for microservices
Cons
- complexity
- cost and shift to infrastructure welcome to Kubernetes and DevOps
- security — now you should secure cross-service communication and another type of traffic in a system. Now you need to introduce Auth services and think about how to manage policies
- distributed transaction handling
Polylith
It came to us from the Clojure community and works well with functional languages but could be applied to nodejs.
So you have a management tool and a big mono repo of building Lego-like blocks that could form a microservice or monolithic app, depending on your need.
Polylith is a software architecture pattern that combines the benefits of monolithic and microservices architectures while addressing some drawbacks. The name “Polylith” is derived from “poly” (meaning “many”) and “lith” (meaning “stone” or “unit”), signifying a structure composed of multiple building blocks. Polylith was introduced by Joakim Tengstrand and Jayway in 2020.
The key concepts of Polylith include:
- Components: Polylith applications are built from smaller, reusable units called components. Components are single-responsibility, self-contained entities that encapsulate a specific piece of functionality. They expose a well-defined interface for communication with other components and can be developed and tested independently.
- Bases: Bases are the foundation upon which components are assembled. They define how components are combined and connected to create a runnable application. A base can be considered a thin layer between the elements and the runtime environment.
- Workspaces: A workspace is a development environment that includes all the components, bases, and related artifacts needed to build, test, and run a Polylith application. Workspaces facilitate development by providing a coherent structure and tools to manage the components and bases.
- Development and deployment flexibility: Polylith promotes a flexible approach to development and deployment. Components can be shared across multiple bases, allowing for code reuse and modular design. Additionally, bases can be deployed as a monolith or as separate microservices, depending on the specific needs and constraints of the project.
- Incremental adoption: Polylith architecture allows for incremental adoption, enabling teams to gradually refactor their existing monolithic applications or microservices into a more modular and maintainable structure.
The Polylith architecture offers several benefits:
- Modularity: By breaking down applications into smaller, reusable components, Polylith encourages the separation of concerns, making it easier to develop, test, and maintain code.
- Code reuse: Components can be shared across multiple applications, improving consistency and reducing code duplication.
- Flexibility: Polylith allows for a flexible deployment strategy, enabling teams to choose between monolithic or microservices deployments based on their specific requirements.
- Simplicity: The Polylith approach simplifies the development process by providing a clear structure and a streamlined development environment, making it easier to reason about the application and its components.
Nano Services
Smaller that service !! single operation as service , function as a service
People see nano service as an antipattern and extreme that create overhead in a system. I see nano services as useful in architectures that allow separate operations from each other. So good example of a nano service could be a lambda function or actor or agent in an actor system or agents mech network.
Actors systems is a topic for a separate article and talk
References
I recommend to read a book on topic of monoliths and microservices