Creating a Modular Monolith: Building Strategies and Insights Gained

Posted by

Modular Monoliths: How To Build One & Lessons Learned

Modular Monoliths: How To Build One & Lessons Learned

When it comes to building software systems, the debate between monoliths and microservices has been ongoing for years. While microservices offer scalability and flexibility, they also come with added complexity and overhead. On the other hand, monoliths are simpler to build and maintain, but can easily become unwieldy and difficult to scale as the codebase grows.

One way to combine the best of both worlds is to build a modular monolith. By breaking down a monolithic application into smaller, more manageable modules, developers can achieve the flexibility of microservices while still enjoying the simplicity of a monolithic architecture. Here are some tips on how to build a modular monolith and lessons learned from those who have done it before:

How To Build A Modular Monolith

  1. Identify Modules: Start by breaking down your application into distinct modules based on functionality or business logic. This will help you organize your codebase and make it easier to manage.
  2. Separate Concerns: Each module should have a clear responsibility and should be isolated from other modules. This will make it easier to test and maintain each module individually.
  3. Define Interfaces: Use well-defined interfaces between modules to ensure loose coupling and easy integration. This will make it easier to swap out modules or add new ones without affecting the entire system.
  4. Centralized Configuration: Manage configuration settings for all modules in a centralized location to ensure consistency and ease of maintenance.
  5. Testing Strategy: Develop a comprehensive testing strategy that includes unit tests for each module, integration tests for module interactions, and end-to-end tests for the entire system.

Lessons Learned

  • Keep Modules Small: Avoid creating modules that are too large or too complex. Smaller modules are easier to understand, test, and maintain.
  • Versioning: Maintain version control for each module to track changes and updates. This will help prevent compatibility issues when updating modules.
  • Documentation: Document each module thoroughly to help developers understand its purpose, functionality, and dependencies.
  • Communication: Ensure clear communication between team members working on different modules to avoid conflicts and ensure seamless integration.
  • Monitor Performance: Keep an eye on the performance of each module and the system as a whole to identify bottlenecks and optimize as needed.

Building a modular monolith can be a great way to strike a balance between the simplicity of a monolithic architecture and the flexibility of microservices. By following these tips and learning from the experiences of others, you can avoid common pitfalls and build a scalable and maintainable application that meets the needs of your business.

0 0 votes
Article Rating
36 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@MilanJovanovicTech
6 months ago

💡You can learn more about Modular Monolith Architecture here: https://bit.ly/3SXlzSt

@Adrianvdh
6 months ago

Please do a video on Eventual Consistency vs Transactional Consistency

@IlyaPermyakov
6 months ago

Thanks for the video, how do you deal with a lot of UI tasks/pages that need to read data from multiple different modules?

@waggerdagger2831
6 months ago

A MM cannot scale horizontally, unless the MM is stateless, is that correct?

@alabidavid4674
6 months ago

I intend to try this out on a nestjs app as I believe the knowledge is transferrable.

My question is this: should every module have only a table? If not, can the tables that are under each modules share foreign keys?

@emreaka3965
6 months ago

Thanks!

@Olosann
6 months ago

Circle of creation 😉 So it's simillar to how SAP or othe big vendors structured their ERP since 80's ?

@Alex-gj2uz
6 months ago

Great explanation, in good detail and also with some realworld "handson" tipps, like the example with internal keyword in c#, the comparison of method calls and message bus etc.

I have one question though:
You say you don't want to share data between modules directly, only go over the modules boundry. Imagine a system where you have a timeseries database, its an industrial edge usecase:
You have one PC which is getting data from 50-100 sensors or controllers, it will collect all the data into the timeseries db every n seconds. Now one other module would like to get some data from the timeseries database, resp. the module which is having this DB.
This means you could only get data via the module interface (messagebus, RPC, REST, what ever), would you really strictly stick to this even you get some performance and complexity drawbacks or would you make some exceptions and access the database directly?

@kodindoyannick5328
6 months ago

Great talk. All the content is useful for me. Thanks you Milan.

@ackuthe6765
6 months ago

I am also software eng.(good one), tried to start with Microservices my app, then realized half-road it is going to fail and fallback to monolith.. don't do this mistake.. before everything it will cost more

@thebowshock7729
6 months ago

Hey Milan. At 42:30 do you mean data denormalization and duplication across multiple isolated databases/ schemas belonging to individual modules?

@stephendgreen1502
6 months ago

It would be nice if .Net catered better for modular monoliths. They are the youngest brother and the older ones, database-centric layered UI/BL/DAL, get all the attention and good stuff. Be nice if having a lot of modules projects within one solution worked better – if the solution could be compiled both in IDE and in Cloud without all the projects having to be at top level within the solution physical folder/files. That sort of thing. To make it more scalable. After all modular monolith arguably is the original and purest architecture – how modules were intended to work.

@georgesngandeu9115
6 months ago

Milan you are very good. Thanks for sharing

@humbertoh9252
6 months ago

Good talk! Monoliths are also horizontal scalable as you can have multiple nodes with the same app. What is harder to horizontal scale is the database.

@infotips2475
6 months ago

Do I still need to implement a saga (or something for consistency) if I use a message broker?, rigth.

@cesarcofg
6 months ago

Awesome presentation MIlan thanks , very clear.

@vilkazz
6 months ago

For us the biggest pain with this architecture was to keep the api layer in check.

Our team opted for hard-coupled api layer between the domains… Which caused every api update to require dependency update in multiple modules.

@danielgruner
6 months ago

I really love how you went through the problems and different solutions for each problem. I stumbled over the repo you mentioned in your video and was a little bit overwhelmed because I didn't get the inter-module communication by event bus. You gave a perfect explanation and a kind of smooth transition from method calls to messaging.

One question (perhaps you have an idea, otherwise perhaps there are others here in the chat with some ideas):

How would you code the module communication by method calls in Node.js? In Node you can do the same thing in tens or hundreds of ways. People coming from OOP languages tend to use classes and patterns like Dependency Injection while others just allow other modules to use an exported function. Is there a way to do it right or wrong?

@Obscurania
6 months ago

Loved this talk. To the point with no fluff and gives actual examples.

@RN-jo8zt
6 months ago

can we use kafka in modular monolithic architecture?
also you mentioned monolithic is communicated by method call. is this means by REST or SOAP api. is not it a network call?
my question releted to modular monolithic not only monolthic .