4 ms·
I find it relatively easy to build "modular monoliths" by starting from "vertical slices"[0] at the outset. Vertical slices being primarily a feature organizat
by CharlieDigital 11mo ago
I find it relatively easy to build "modular monoliths" by starting from "vertical slices"[0] at the outset. Vertical slices being primarily a feature organization strategy scales well pragmatically over time, IME. So when first starting out, you can keep it simple and just one monolith and one unit of deployment, but keep everything separated into their own feature folders with common things in a `shared` folder. When you get further along, it is possible to consider splitting things out by feature teams (if that's what works best) and still keep one runtime (just enabling/disabling different features at startup).
The common bits can eventually be moved into a package dependency and referenced. Separate features if they become large enough can also be moved into separate packages, but part of the same monolithic codebase.
In some cases, it can be easier still and just ship the entire runtime as-is (without any additional work to enable modularity) and simply route different endpoints (e.g. https://feature1.domain.com https://feature1.domain.com -> node set 1, https://feature2.domain.com https://feature2.domain.com -> node set 2) so you still have the option to monitor and scale the features differently based on their load profile and needs. This works great as long as cold starts are not a big concern (thereby adding a requirement for minimizing package size).
I find this particularly easy on AWS, especially when deploying with Copilot CLI[1] because it makes it relatively easy to just route different sub-domains to different target groups. Now you have one singular container image that just gets scaled differently by route (e.g. a high volume feature gets bigger nodes and a dedicated route in Route 53).
I find some teams have trouble thinking this way because devs many times are not involved enough in the deploy time considerations. For more involved app-level partitioning of modules, I have a practical example in C#[2] that would work equally well with something like Nest.js (or Elysia or Hono) by simply using environment variables to declare a "feature role" for the instance and dynamically enabling/disabling feature modules.
[0] https://www.jimmybogard.com/vertical-slice-architecture/ https://www.jimmybogard.com/vertical-slice-architecture/
[1] https://aws.github.io/copilot-cli/ https://aws.github.io/copilot-cli/
[2] https://github.com/CharlieDigital/dn8-modular-monolith https://github.com/CharlieDigital/dn8-modular-monolith