2.4 KiB
ADR 0001: Govern as a Modular Monolith
Status: Accepted
Date: 2026-07-29
Context
The application is deployed on a LAN NAS as one Docker container with a Python HTTP process, SQLite, a build-free browser client, scheduled refresh work, external market providers, and LLM features. Product breadth has grown, while routing, persistence, frontend state, and CSS remain concentrated in a few large files.
The system may later become internet-facing, gain more features, replace SQLite, or move jobs to workers. It does not currently have load or team boundaries that justify distributed services.
Decision
Retain one deployable application and introduce strict internal modules, ports, adapters, feature registries, data contracts, repository contracts, and regression gates.
The deployment remains:
one image + one application process + one persistent data volume + port 8765
Internal code moves toward:
delivery -> application services -> ports -> infrastructure
Compatibility facades permit incremental migration. No feature is rewritten solely to match the target directory structure.
Consequences
Positive
- Current NAS deployment stays simple.
- Refactoring can proceed in reversible stages.
- Feature ownership and account boundaries become visible.
- Data, database, LLM, and job adapters can be replaced later.
- A measured hotspot can be extracted without first untangling business logic.
Costs
- The transition temporarily contains old and new entrypoints.
- Boundary tests and registries require ongoing maintenance.
- A single process remains a capacity and fault-isolation limit until infrastructure is deliberately extracted.
Rejected Alternatives
Immediate microservices
Rejected because they add network contracts, service discovery, deployment coordination, distributed tracing, and failure modes before load requires them.
Full framework rewrite
Rejected because replacing the HTTP and frontend frameworks while moving boundaries would combine structural and behavioral risk.
Continue patching flat modules
Rejected because current file size, direct provider creation, global page state, and CSS override layers already make regressions difficult to isolate.
Revisit Conditions
Reconsider service extraction when one module has independently measured scaling needs, requires a separate availability boundary, or needs an independent release lifecycle.