The Monolith Is Not the Enemy
Somewhere around 2016, the software industry decided that monoliths were the enemy. If your application ran as a single deployable unit, you were doing it wrong. The future was microservices: dozens o
Somewhere around 2016, the software industry decided that monoliths were the enemy. If your application ran as a single deployable unit, you were doing it wrong. The future was microservices: dozens of independently deployed services communicating over HTTP, each owned by a different team, each with its own database.
Eight years later, the wreckage is visible everywhere. Companies with three engineers running twelve services. Distributed debugging sessions that take longer than the original bug would have taken to fix in a monolith. Network partitions causing cascading failures that a function call would have handled gracefully.
The Microservices Sales Pitch
The pitch was compelling: independent deployment, technology diversity, team autonomy, horizontal scaling. Each service does one thing well. Teams move fast because they do not step on each other's code.
This pitch is accurate — for organizations with hundreds of engineers, dozens of teams, and products that genuinely have distinct bounded contexts. Netflix needs microservices. Uber needs microservices. Your B2B SaaS with four developers does not.
What Microservices Actually Cost
Operational complexity. Every service needs its own CI/CD pipeline, monitoring, logging, alerting, deployment strategy, and on-call rotation. A monolith needs one of each. Ten services need ten of each — or a platform team to abstract it away, which is its own cost.
Distributed system problems. Network calls fail. Services go down. Data consistency across services requires sagas, eventual consistency patterns, or distributed transactions. A function call in a monolith either succeeds or throws an exception. A network call between services can succeed on one end and fail on the other.
Developer experience. Running the full system locally means running all services locally, or maintaining a shared development environment that drifts from production. Debugging means correlating logs across services, tracing requests through multiple hops, and understanding failure modes that do not exist in a monolith.
Refactoring friction. Moving code between services means changing APIs, updating contracts, coordinating deployments. Moving code between modules in a monolith means moving a file.
The Monolith Advantages Nobody Talks About
Simplicity. One codebase, one deployment, one database, one set of logs. A new developer can clone one repo and understand the entire system.
Refactoring ease. Your IDE can rename a function across the entire codebase. Try that across twelve services.
Consistency. Transactions are local. Data integrity is enforced by the database, not by hope and eventual consistency.
Performance. Function calls are nanoseconds. HTTP calls are milliseconds. That difference compounds across every interaction in your system.
Our Approach
At Anethoth, each product — DocuMint, CronPing, FlagBit, WebhookVault — is a monolith. FastAPI application, SQLite database, single Docker container. Each one handles everything: authentication, business logic, Stripe integration, API documentation.
We are not anti-microservices. We are anti-premature-microservices. The monolith is not the enemy. Premature complexity is.
Start with a monolith. Extract services when you have evidence — not opinions — that you need them. Your future self will thank you.