All checks were successful
Build, test and publish / verify (push) Successful in 8m15s
216 lines
10 KiB
Markdown
216 lines
10 KiB
Markdown
**ID:** ADR1 \
|
|
**Title:** Application size \
|
|
**Supersedes:** - \
|
|
**Status:** APPROVED \
|
|
**Expiration Date:** Six months after approval; record the calendar date upon manual approval.
|
|
|
|
## Context
|
|
|
|
Agile Dancers currently keeps its frontend, backend, CI pipeline, skills,
|
|
specifications, ADRs, and other documentation in one repository. As the application
|
|
grows, humans and agents need more context to understand individual tasks.
|
|
Functional dependencies can become entangled, making changes and reuse harder.
|
|
|
|
The primary goal is to reduce the context required for a task. Supporting goals
|
|
are preventing uncontrolled coupling and enabling reuse and replacement of
|
|
capabilities. Repository organization, module boundaries, and deployment
|
|
boundaries are separate architectural choices.
|
|
|
|
Business capabilities stand on their own, while an application system may support
|
|
multiple capabilities. Loosely coupled capability boundaries allow implementations
|
|
to change between custom software, libraries, and externally supplied components.
|
|
Scheduling and school administration are candidate areas to examine; their exact
|
|
system boundaries have not yet been decided.
|
|
|
|
Code-level modularity alone is insufficient when shared tables, materialized
|
|
views, SQL scripts, or other database access bypass module boundaries. Separate
|
|
services would have the same weakness without enforced data ownership.
|
|
|
|
Systems can initially run on the same physical server. Independent workload
|
|
placement is nevertheless useful: computational work, such as runners and future
|
|
scheduling calculations, may run on a mini-PC rather than the Synology. Independent
|
|
scaling and release cycles are future possibilities rather than universal current
|
|
requirements. Colocation reduces network exposure but process restarts, timeouts,
|
|
and resource contention still require defined failure behavior.
|
|
|
|
Reusable engineering resources should also support other projects. Specifications
|
|
can affect several projects, and ADRs apply across the application landscape.
|
|
|
|
## Decisions
|
|
|
|
### Capabilities and systems
|
|
|
|
Organize the landscape into independently deployable systems. Group capabilities
|
|
into systems according to cohesion, data ownership, replacement needs, and
|
|
operational requirements, including workload placement. Capability size alone does
|
|
not justify a separate system.
|
|
|
|
Each system has its own repository and independent deployment lifecycle. Within a
|
|
system, use modules to keep its capabilities loosely coupled. A capability does
|
|
not automatically require its own service or deployment. Compute workers may be
|
|
deployed separately from the business system that delegates work to them.
|
|
|
|
Capability contracts should allow implementations to be replaced by custom code,
|
|
libraries, or external products, using adapters where necessary.
|
|
|
|
### Data ownership
|
|
|
|
Each system exclusively owns its data. Other systems access that data through
|
|
explicit contracts, never through direct access to its storage. This restriction
|
|
also applies to reporting queries, views, migrations, and maintenance scripts.
|
|
Cross-system reporting requires explicit contracts or a separately owned
|
|
projection.
|
|
|
|
PostgreSQL-backed systems initially share one PostgreSQL server/container, with
|
|
separate databases or schemas and separate credentials whose permissions enforce
|
|
ownership. Sharing physical infrastructure does not permit sharing storage access.
|
|
Systems may choose other storage technologies when justified. This permits future
|
|
CQRS designs without adopting CQRS through this ADR.
|
|
|
|
### Contracts and communication
|
|
|
|
Systems communicate through explicit, versioned contracts. Internal domain models
|
|
and persistence entities remain private to their owning system and are not shared
|
|
through common libraries. Contract definitions and generated clients may be shared.
|
|
|
|
Choose synchronous APIs or asynchronous messaging for each interaction according
|
|
to its needs. Define failure behavior for each interaction. This ADR mandates
|
|
neither a landscape-wide communication mechanism nor a message broker.
|
|
|
|
### Landscape and engineering resources
|
|
|
|
Maintain a landscape repository containing ADRs, specifications, and the capability
|
|
and system map. Specifications identify the projects they affect and may span
|
|
multiple systems. ADRs govern the application landscape according to their scope.
|
|
Each system retains a README describing its implementation and operation.
|
|
|
|
Maintain reusable engineering resources, including pipeline components, skills,
|
|
and general engineering documentation, separately from the landscape repository
|
|
and individual systems. Group these resources according to maintenance and release
|
|
needs; a separate repository per resource type is not required. Version shared
|
|
resources so consuming projects can adopt updates deliberately.
|
|
|
|
### Adoption and review
|
|
|
|
Use this ADR as guidance and the starting point for follow-up specifications.
|
|
Detailed system boundaries, contracts, and migration designs are follow-up work.
|
|
Migrate incrementally, keeping the application working after each extraction.
|
|
|
|
Perform an initial review six months after approval. Review earlier if contract
|
|
coordination, operational overhead, or persistent cross-system coupling becomes a
|
|
significant burden. The expiration date triggers reevaluation and does not
|
|
automatically invalidate the decision.
|
|
|
|
## Options considered
|
|
|
|
### 1. Improve navigation within the current structure
|
|
|
|
Keep the existing projects and deployment structure, improving focused
|
|
documentation, task guidance, and file organization.
|
|
|
|
Pros:
|
|
|
|
- Requires little disruption or migration work.
|
|
- Makes relevant context easier to find.
|
|
- Retains simple local development and coordinated changes.
|
|
|
|
Cons:
|
|
|
|
- Offers limited protection against functional entanglement.
|
|
- Does not enforce data ownership or support independent workload placement.
|
|
- Leaves reuse and replacement dependent on existing application boundaries.
|
|
|
|
Not chosen because navigation improvements alone do not establish the ownership
|
|
and replacement boundaries needed as the landscape grows.
|
|
|
|
### 2. Modular monolith in one repository
|
|
|
|
Organize capabilities into modules with explicit interfaces and dependency rules,
|
|
while retaining coordinated deployment and one repository.
|
|
|
|
Pros:
|
|
|
|
- Reduces the code area needed to understand a capability.
|
|
- Enables dependency checks and straightforward changes across modules.
|
|
- Keeps deployment and in-process communication simple.
|
|
|
|
Cons:
|
|
|
|
- Shared database access can bypass code-level boundaries through tables, views,
|
|
and scripts unless storage ownership is separately enforced.
|
|
- Workload placement and deployment remain coupled.
|
|
- Independent replacement and reuse may require later extraction.
|
|
|
|
Not chosen as the landscape-wide approach because independently enforced ownership
|
|
and deployment boundaries are desired. Modular design remains part of the chosen
|
|
approach inside each system.
|
|
|
|
### 3. Separate projects and repositories with coordinated deployment
|
|
|
|
Extract capabilities into separately built libraries or applications with
|
|
versioned contracts, while retaining a coordinated deployment lifecycle.
|
|
|
|
Pros:
|
|
|
|
- Separates source and build context.
|
|
- Gives reusable components their own versioned releases.
|
|
- Retains a coordinated operational release process.
|
|
|
|
Cons:
|
|
|
|
- Changes spanning repositories require dependency release coordination.
|
|
- Deployment remains coupled despite repository separation.
|
|
- Repository separation alone does not enforce storage ownership or runtime
|
|
independence.
|
|
|
|
Not chosen because it incurs repository coordination costs while retaining a
|
|
deployment constraint that would limit workload placement and replacement.
|
|
|
|
### 4. Independently deployable systems with internal capability modules — chosen
|
|
|
|
Give systems their own repositories, deployment lifecycles, contracts, and enforced
|
|
data ownership. Keep capabilities loosely coupled through modules within a system.
|
|
Place compute workers independently where useful.
|
|
|
|
Pros:
|
|
|
|
- Supports focused development context and independent system evolution.
|
|
- Enforces data ownership beyond code dependency rules through storage permissions.
|
|
- Allows workloads to move between the Synology and mini-PC.
|
|
- Supports capability replacement and reuse through explicit contracts.
|
|
- Allows storage technology choices per system.
|
|
|
|
Cons:
|
|
|
|
- Requires contract compatibility and coordination for changes spanning systems.
|
|
- Adds deployment, configuration, and operational maintenance for multiple processes.
|
|
- Requires explicit failure handling and cross-system consistency decisions.
|
|
- Sharing one server or PostgreSQL instance retains common infrastructure failure
|
|
points despite logical isolation.
|
|
|
|
Chosen because ownership, replaceability, focused context, and independent workload
|
|
placement outweigh the additional operational and contract coordination work.
|
|
|
|
## Consequences
|
|
|
|
- Write follow-up specifications to map capabilities and dependencies, choose
|
|
initial system boundaries, define contracts and data ownership, and plan
|
|
extraction. This ADR does not itself settle those boundaries or implement them.
|
|
- Establish the landscape repository and the repositories and versioning needed
|
|
for reusable engineering resources. Preserve links between specifications and
|
|
affected projects, and between system READMEs and landscape guidance.
|
|
- Extract systems one at a time, establishing contracts and enforcing storage
|
|
ownership as part of each extraction. Moving tables into separate schemas is
|
|
insufficient while cross-system SQL access remains possible.
|
|
- Adapt build and deployment pipelines to release systems independently and
|
|
consume versioned shared engineering resources.
|
|
- Add appropriate checks for module dependencies, contract compatibility, and
|
|
storage isolation. Include views and scripts in boundary enforcement.
|
|
- Specify how systems exchange information, handle failed interactions, and keep
|
|
derived information consistent. These choices belong to the relevant follow-up
|
|
specifications rather than a universal messaging requirement.
|
|
- Keep one PostgreSQL container initially. Detailed backup and failover design is
|
|
future work; logical data separation does not provide infrastructure failover.
|
|
- Record the calendar review date when a maintainer manually approves this ADR.
|
|
REFINED records the agreed proposal; approval remains a separate manual step.
|