Earlier quoted context omitted.
Monoliths don’t actually look like that at scale. For example you can easily have multiple different data stores for different reasons, including multiple different kinds of databases. Here’s this tiny little internal relational database used internally, and there’s the giant tape library that’s archiving all this scientific data we actually care about. Here’s the hard real time system, and over there’s the billing d…
But all those data sources are connected to from the same runtime, right? And to run it locally you need access to dev versions of all of them. And when there’s a security vulnerability in your comment system your tape library gets wiped.
> But all those data sources are connected to from the same runtime, right?
Surely you could have multiple instances of your monolithic app:
# Runs internally
app_instance_1_admin_interface:
environment:
FEATURE_ENABLE_ADMIN_INTERFACE=true
# Runs interally
app_instance_2_tape_backup_job:
environment:
FEATURE_ENABLE_TAPE_BACKUP_JOB=true
# Exposed externally through LB
app_instance_3_comment_system:
environment:
FEATURE_ENABLE_COMMENT_SYSTEM=true
If the actual code doesn't violate the 12 Factor App principles, there should be no problems with these runtimes working in parallel: https://12factor.net/ (e.g. storing data in memory vs in something external like Redis, or using the file system for storage vs something like S3)> And to run it locally you need access to dev versions of all of them.
With the above, that's no longer necessary. Even in the more traditional monolithic profiles without explicit feature flags at work, i still have different run profiles.
Do i want to connect to a live data source and work with some of the test data on the shared dev server? I can probably do that. Do i want to just mock the functionality instead and use some customizable data generation logic for testing? Maybe a local database instance that's running in a container so i don't have to deal with the VPN slowness? Or maybe switch between a local service that i have running locally and another one on the dev server, to see whether they differ in any way?
All of that is easily possible nowadays.
> And when there’s a security vulnerability in your comment system your tape library gets wiped.
Unless the code for the comment system isn't loaded, because the functionality isn't enabled.
This last bit is where i think everything falls apart. Too many frameworks out there are okay with "magic" - taking away control over how your code and its dependencies are initialized, oftentimes doing so dynamically with overcomplicated logic (such as DI in the Spring framework in Java), vs the startup of your application's threads being a matter of a long list of features and their corresponding feature flag/configuration checks in your programming language of choice.
Personally, i feel that in that particular regard, we'd benefit more from a lack of reflection, DSLs, configuration in XML/YAML etc., at least when you're trying to replace writing code in your actual programming language with those, as opposed to using any of them as simple key-value stores for your code to process.