Iterate at lightning speed
One of the most significant decisions you must make is when and if to move to a modular architecture. Chances are, you started your business with a monolith architecture. Monolith architecture enables you to move fast prototyping MVP features and pivot quickly since one person or a team controls the entire application. You either started with a unicorn developer who builds your entire app or a small team. As your team grew, you began to split those teams along feature or functional areas of your product. Now, your teams are feeling the pain of maintaining the monolith and chances are only one team can deploy at a time.
Should your team encounter a bug, they must wait for the other teams to deploy their changes before they can deploy their fix or tell the other teams to wait for the fix before they can deploy. This blockage is a massive bottleneck in your development process. As you start feeling this pain, you might consider moving to modular architecture and enabling your teams to iterate quickly and independently.
While there are many benefits to modular architecture, there are also many challenges. One of the biggest challenges is how to deploy many times a day. If you have an operational team doing all the deploys, you need to increase its throughput. You will face a decision to either hire more people or create multi-functional teams with embedded DevOps. Furthermore, your operational team is likely monitoring the SLA of your application. With the move to modular architecture, you will need to monitor the SLA of each module or microservice.
Suppose you have engineering teams do their deploys and monitor the SLAs. In that case, you will need to upskill your teams in operational knowledge and separate your deployment pipelines, with every module/microservice having its own pipeline. These efforts will take time and resources.
The drawback of deploying modular architecture is maintaining many pipelines. Consider using a CI/CD platform at this stage. In addition, if you are creating artifacts for different modules, you will run into what's known as dependency hell, where continuous integration becomes difficult as many versions of artifacts are being released independently of each other. You need to enable tooling in your CI/CD process to manage and integrate the dependencies.
Finally, suppose you decide to put the operational burden on your engineering teams. In that case, you will make them operationally excellent but less creative and innovative, as a significant part of their time will be spent on operational tasks. You will need to decide if you want a lean feature-focused engineering team or a cross-functional, operationally excellent team.
When we built out the highly modular architecture for the cloud platform at Mastercard, we achieved continuous delivery with 100% automated testing and deployment. We isolated each engineering team and product to separate cloud environments and built many platform artifacts. We deployed each artifact separately from the other and made custom tooling to continuously update the dependencies in the services depending on the artifacts. We immediately put those artifacts into regression testing at the service level. The extensive usage of artifacts created a highly complex dependency graph we had to manage.
This approach worked because of our investment in tooling. We were iterating and putting platform artifacts and new service features into production multiple times a day, which allowed us to have quick feedback cycles and get changes to customers fast. However, we needed to invest time and resources upfront to build the platform and tooling.
The drawing below illustrates the difference between deploying a monolith and a modular architecture.