Start With Less, Add When It Hurts
Why starting simple and adding complexity only when the pain is real leads to better architecture than planning for every scenario upfront.
The Temptation
When starting a new project, it’s tempting to set up everything “properly” from day one: microservices, event sourcing, CQRS, Kubernetes, the full stack. The reasoning is sound — “we’ll need it eventually, so why not start right?”
Vivolar taught me the answer: because you don’t know what “right” looks like until you’ve built something.
What We Started With
Sprint 1 was dead simple:
- Monolithic Spring Boot app
- Direct service calls between packages
- Basic CRUD with JPA
- Simple React pages with fetch calls
No events, no module boundaries, no AI integration, no sophisticated error handling.
When Complexity Was Earned
Each architectural improvement came from real pain:
Module boundaries (ArchUnit) — added after noticing that ItemService had accumulated 8 dependencies. The pain was real: changes in one area cascaded into unrelated areas. The fix was enforceable module boundaries.
Event-driven design (ADR-001) — added after audit logging, notifications, and analytics each added new dependencies to core services. The pain: every new cross-cutting concern required modifying existing services. The fix: publish events, let listeners handle side effects.
TestContainers — added after a mock-based test passed but production broke due to a column type mismatch. The pain was a production bug that tests should have caught. The fix: test against real infrastructure.
Pre-deployment validation — added after a CORS misconfiguration broke production. The pain: a preventable deployment failure. The fix: an automated checklist that catches common mistakes.
The Pattern
Every good architectural decision in Vivolar followed the same pattern:
- Start simple
- Notice the pain (coupling, bugs, deployment failures)
- Understand why the current approach doesn’t work
- Add the minimum complexity to solve the actual problem
- Document the decision (ADR) so future you remembers why
The Anti-Pattern
The decisions I regret were the opposite: adding complexity before the pain materialized.
Early on, I over-engineered the category system with a complex hierarchy anticipating future needs. Most of that complexity was never used and had to be simplified later.
The Takeaway
Architecture is not a one-time design exercise — it’s an ongoing response to real problems. The best architecture for day one is almost never the best architecture for day one hundred. And that’s fine, as long as your codebase is structured to evolve.
The modular monolith pattern makes this explicit: strict boundaries today, extraction tomorrow if needed. You earn the complexity when the pain is real, not when the whiteboard says you might need it.