Skip to main content

Architecture Principles

Purpose

This document defines the non-negotiable architectural principles for projects using AI contextFlow.

It exists to prevent architectural drift, uncontrolled coupling, and short-term implementation decisions that degrade long-term maintainability.

These principles are intentionally technology-agnostic.


Scope

These principles apply to:

  • System structure and modularization
  • Dependency direction and boundaries
  • Interface design and contracts
  • Evolution and change management

If a project deviates from these principles, the deviation must be explicit and justified.


Core Goals

  • Maintain clear boundaries between concerns
  • Enable change with low risk and predictable impact
  • Support long-term maintainability and testability
  • Prevent uncontrolled coupling and implicit dependencies

1. Explicit Boundaries

  • Organize the system into modules with clear responsibilities.
  • A module must have a clear purpose and a stable public interface.
  • Avoid "god" modules that accumulate unrelated responsibilities.

Rule of thumb: If a module cannot be explained in one sentence, it is likely too broad.


2. Dependency Direction

  • Dependencies must point from higher-level policy to lower-level details.
  • Domain or core logic must not depend on infrastructure or UI concerns.
  • Prevent cyclic dependencies.

Enforcement: If dependency direction is unclear, refactor the boundary.


3. Contracts Over Knowledge

  • Prefer explicit interfaces/contracts over implicit knowledge of internals.
  • Avoid reaching into internals of other modules.
  • Treat external integrations as unstable: isolate them behind adapters.

4. Keep the Domain Clean

  • Central business rules should be explicit and testable.
  • Avoid mixing domain logic with persistence, networking, or UI code.
  • Domain logic must be easy to unit test.

5. Composition Over Framework Lock-In

  • Frameworks should be treated as tools, not as architecture.
  • Keep core logic framework-independent where feasible.
  • Avoid coupling business rules directly to framework constructs.

6. Prefer a Modular Monolith by Default

  • Start as a modular monolith unless there is a strong, validated reason to split into services.
  • Services introduce operational and coordination overhead.
  • Split only when boundaries are proven and required.

7. Data Ownership and Consistency

  • Each module owns its data and invariants.
  • Avoid shared mutable state across modules.
  • Define data contracts explicitly.

8. Evolve Through Small, Safe Steps

  • Prefer incremental evolution over large rewrites.
  • Structural changes must be supported by tests and/or characterization tests.
  • Avoid redesigning architecture without concrete pressure.

9. Document Long-Term Decisions

Use Architecture Decision Records (ADRs) when:

  • A decision affects system structure long-term
  • A decision is hard to reverse
  • A decision introduces significant trade-offs

If it matters in six months, it deserves an ADR.


10. Quality as Architecture

Architecture is not just structure — it includes:

  • testability
  • observability
  • operability
  • security

If a design cannot be tested or operated, it is not complete.


Quality Gates

A change is architecturally acceptable only if:

  • Boundaries remain clear
  • Dependency direction is preserved
  • Coupling is not increased without explicit justification
  • Long-term decisions are documented

Anti-Patterns

  • Implicit module coupling ("just call it directly")
  • Cyclic dependencies
  • Framework-first design (architecture = framework)
  • Shared mutable state across modules
  • Large rewrites without pressure or test safety

Status

These principles are intentionally conservative.

They are designed to keep a codebase understandable and maintainable under intensive AI-assisted development.