Files
template/docs/ARCHITECTURE.md
2026-06-28 09:48:34 +02:00

6.8 KiB

Architecture

This document describes the structure, boundaries, flows, and technical rules of the system.

For project intent and runtime facts, see PROJECT.md. For coding standards, see CONVENTIONS.md. For recorded trade-offs, see DECISIONS.md.

High-Level Overview

{{PROJECT_NAME}} uses {{ARCHITECTURE_STYLE}} to support {{PRIMARY_USE_CASES}}.

Replace this section with a concise explanation of the system's major parts, their responsibilities, and the constraints that shaped the architecture.

flowchart LR
    User["User or External Client"]
    Interface["Interface Layer<br/>API, UI, CLI, Worker"]
    Application["Application Layer<br/>Use cases and orchestration"]
    Domain["Domain Layer<br/>Rules and invariants"]
    Infrastructure["Infrastructure Layer<br/>Database, queues, files, services"]
    External["External Systems"]

    User --> Interface
    Interface --> Application
    Application --> Domain
    Application --> Infrastructure
    Infrastructure --> External

Architecture Style

Field Value
Style {{ARCHITECTURE_STYLE}}
Primary reason {{ARCHITECTURE_REASON}}
Main trade-off {{ARCHITECTURE_TRADE_OFF}}
Related decision DECISIONS.md

Common examples include layered architecture, modular monolith, microservices, event-driven architecture, hexagonal architecture, desktop MVC/MVVM, or game-specific entity/component systems.

Folder Structure

{{PROJECT_ROOT}}/
  {{SOURCE_FOLDER}}/
  {{TEST_FOLDER}}/
  {{DOCS_FOLDER}}/
  {{BUILD_FOLDER}}/
Folder Responsibility
{{FOLDER}} {{FOLDER_RESPONSIBILITY}}

Keep generated files, build outputs, and framework artifacts out of source folders unless the framework requires them.

Module Responsibilities

Module Responsibility Owned Data Public Interface
{{MODULE_NAME}} {{MODULE_RESPONSIBILITY}} {{OWNED_DATA}} {{PUBLIC_INTERFACE}}

Modules should have clear ownership. Shared utilities should remain small and generic; domain behavior belongs with the module that owns the domain concept.

Dependency Rules

Define allowed dependencies explicitly.

  • {{DEPENDENCY_RULE_1}}
  • {{DEPENDENCY_RULE_2}}
  • {{DEPENDENCY_RULE_3}}

Recommended default:

flowchart TD
    UI["UI, API, CLI, Worker"]
    App["Application"]
    Domain["Domain"]
    Infra["Infrastructure"]

    UI --> App
    App --> Domain
    App --> Infra
    Infra --> Domain

Domain code should not depend on delivery mechanisms, databases, network clients, or framework-specific runtime concerns unless the project intentionally uses an architecture where that trade-off is accepted and recorded.

Persistence Boundary

The default persistence boundary is the repository pattern.

Use repositories to express domain-specific persistence operations without leaking database, ORM, file-system, or external storage details into application or domain logic.

Default rules:

  • Application or domain-facing code depends on repository interfaces.
  • Infrastructure implements repository interfaces.
  • Repositories are named around domain concepts, not database tables.
  • Repositories expose intention-revealing operations, not generic CRUD by default.
  • Transaction boundaries are explicit at the application service, unit of work, or framework boundary selected by the project.

If a project intentionally avoids repositories because the framework or architecture provides a better persistence boundary, record that decision in DECISIONS.md.

Request Flow

sequenceDiagram
    participant Client
    participant Interface
    participant Application
    participant Domain
    participant Infrastructure

    Client->>Interface: Request or command
    Interface->>Application: Validate transport shape
    Application->>Domain: Execute business rule
    Application->>Infrastructure: Persist or integrate
    Infrastructure-->>Application: Result
    Application-->>Interface: Response model
    Interface-->>Client: Response

Document deviations for async jobs, desktop workflows, games, or event-driven flows.

Data Flow

Data Source Owner Storage Consumers
{{DATA_ENTITY}} {{DATA_SOURCE}} {{DATA_OWNER}} {{DATA_STORAGE}} {{DATA_CONSUMERS}}

Data ownership should be clear before adding shared tables, shared schemas, cross-service writes, or replicated state.

Domain Model

Concept Meaning Invariants
{{DOMAIN_CONCEPT}} {{DOMAIN_MEANING}} {{DOMAIN_INVARIANTS}}

Use this section for durable business concepts, not framework models or DTOs.

Integration Points

Integration Direction Protocol Reliability Expectations
{{INTEGRATION_NAME}} {{INBOUND_OR_OUTBOUND}} {{PROTOCOL}} {{RELIABILITY_EXPECTATIONS}}

For each integration, document authentication, retry behavior, timeouts, idempotency, and failure handling.

Security

Area Policy
Authentication {{AUTHENTICATION_POLICY}}
Authorization {{AUTHORIZATION_POLICY}}
Secrets {{SECRETS_POLICY}}
Input validation {{INPUT_VALIDATION_POLICY}}
Output encoding {{OUTPUT_ENCODING_POLICY}}
Audit logging {{AUDIT_LOGGING_POLICY}}
Dependency security {{DEPENDENCY_SECURITY_POLICY}}

Security-sensitive decisions should be recorded in DECISIONS.md.

Error Handling

Error Type Handling Policy User/Client Response
Validation error {{VALIDATION_ERROR_POLICY}} {{VALIDATION_RESPONSE}}
Domain error {{DOMAIN_ERROR_POLICY}} {{DOMAIN_RESPONSE}}
Infrastructure error {{INFRASTRUCTURE_ERROR_POLICY}} {{INFRASTRUCTURE_RESPONSE}}
Unexpected error {{UNEXPECTED_ERROR_POLICY}} {{UNEXPECTED_RESPONSE}}

Errors should preserve enough diagnostic context for operators without exposing secrets or internal implementation details to users.

Performance

Concern Expectation Measurement
Latency {{LATENCY_EXPECTATION}} {{LATENCY_MEASUREMENT}}
Throughput {{THROUGHPUT_EXPECTATION}} {{THROUGHPUT_MEASUREMENT}}
Resource usage {{RESOURCE_EXPECTATION}} {{RESOURCE_MEASUREMENT}}

Document known hot paths and the expected performance test strategy.

Scalability

Dimension Current Strategy Future Strategy
Traffic {{TRAFFIC_STRATEGY}} {{TRAFFIC_FUTURE_STRATEGY}}
Data volume {{DATA_VOLUME_STRATEGY}} {{DATA_VOLUME_FUTURE_STRATEGY}}
Team size {{TEAM_SCALE_STRATEGY}} {{TEAM_SCALE_FUTURE_STRATEGY}}

Scalability work should be driven by measured pressure or clear product requirements, not premature complexity.