---
description: "CodeWiki Architecture and system design pitfalls and review checks"
globs: []
alwaysApply: false
---

# Architecture and system design rules

This track covers more than one language, so no file globs are inferred. Apply these rules manually when they are relevant.

- “Use Kafka” or “move to microservices” is a conclusion.
  Why: It does not name the quality attribute being protected, the options declined, or the condition that should trigger reconsideration.
  Source: [Architecture decision records](https://codewiki.com/architecture/adr/)
- Do not assume this is safe: when an ADR is written after implementation, authors can turn known outcomes into supposed predictions and omit options that were reasonable but failed.
  Source: [Architecture decision records](https://codewiki.com/architecture/adr/)
- Editing an old ADR's decision and rationale to match the current system makes old commits contradict the document and erases why the architecture changed.
  Source: [Architecture decision records](https://codewiki.com/architecture/adr/)
- Requiring an ADR for every technical choice produces files nobody reads; treating signature count as a quality metric delays small, reversible decisions.
  Source: [Architecture decision records](https://codewiki.com/architecture/adr/)
- A consequence such as “lower latency” or “better reliability” cannot be judged after implementation when it has no metric, boundary, or observation method.
  Source: [Architecture decision records](https://codewiki.com/architecture/adr/)
- Memorizing CAP as “always pick two,” then making the whole system sacrifice one property forever.
  Source: [CAP theorem](https://codewiki.com/architecture/cap-theorem/)
- Do not treat CAP consistency, ACID consistency, and replicas eventually matching as the same guarantee.
  Source: [CAP theorem](https://codewiki.com/architecture/cap-theorem/)
- Do not assume this is safe: declaring a vendor or database `CP` or `AP` without accounting for configuration, API, and fault scope.
  Source: [CAP theorem](https://codewiki.com/architecture/cap-theorem/)
- Do not assume this is safe: retrying a write automatically after a timeout and assuming the first attempt did not commit.
  Source: [CAP theorem](https://codewiki.com/architecture/cap-theorem/)
- Using quorum arithmetic or wall-clock last-write-wins and claiming that all conflicts are solved.
  Source: [CAP theorem](https://codewiki.com/architecture/cap-theorem/)
- A team decides on microservices, event-driven design, or a layering template, then defends it with vague benefits.
  Why: The pattern name replaces the problem statement, while the cost of splitting appears only in production. Fix: Write the decision boundary, hard constraints, and quality scenarios first, with the status quo as an option. Adopt a new structure only when it solves a confirmed problem and its benefit exceeds migration and operating cost.
  Source: [Software architecture](https://codewiki.com/architecture/getting-started/)
- "Scalable," "highly available," and "low latency" have no stimulus, environment, response, or measure.
  Why: Every candidate can satisfy those words in conversation, leaving the review to argue about preferences. Fix: Rewrite adjectives as executable scenarios: say where load or failure originates, how the system may degrade, and which test or signal judges the result. Mark a goal as an assumption rather than a fact when it can't yet be verified.
  Source: [Software architecture](https://codewiki.com/architecture/getting-started/)
- A box diagram shows components but omits protocols, data ownership, dependency direction, and failure semantics.
  Why: Different readers give the same line different meanings, and code can still bypass every boundary in the picture. Fix: Label each relationship's purpose and direction, and record timeouts, retries, and consistency for important interactions. Enforce the most important boundaries with import rules, permissions, or contract tests.
  Source: [Software architecture](https://codewiki.com/architecture/getting-started/)
- A design adds replicas, queues, caches, and services while chasing maximum reliability, minimum latency, minimum cost, and strongest isolation at once.
  Why: Every mechanism adds failure modes and maintenance work of its own. Fix: Rank quality attributes, assign budgets, preserve non-negotiable constraints, and record what the choice sacrifices. Choose the simplest design that meets current scenarios, and defer reversible choices until evidence arrives.
  Source: [Software architecture](https://codewiki.com/architecture/getting-started/)
- Architecture documents describe a target state after production code has moved elsewhere, but the team keeps treating the old diagram as fact.
  Why: New contributors build against the wrong boundaries and accelerate the drift. Fix: Mark every diagram with scope and date, automate stable rules, and periodically compare documents with dependency graphs, deployment manifests, and telemetry. Create a new ADR when a decision changes; don't rewrite the old one to match the present.
  Source: [Software architecture](https://codewiki.com/architecture/getting-started/)
- Reading SRP as “one method per class” produces many tiny classes that only forward calls.
  Source: [SOLID principles](https://codewiki.com/architecture/solid-principles/)
- Creating a matching interface for every concrete class and turning every imagined variation into a plugin makes OCP speculation-driven.
  Source: [SOLID principles](https://codewiki.com/architecture/solid-principles/)
- Do not treat successful type checking as proof of LSP misses stricter inputs, weaker outputs, and new exceptions.
  Source: [SOLID principles](https://codewiki.com/architecture/solid-principles/)
- Claiming DIP after adopting a dependency-injection container may only hide concrete dependencies behind a registry and string tokens.
  Source: [SOLID principles](https://codewiki.com/architecture/solid-principles/)
- Do not assume this is safe: forcing all five principles around a stable small function adds navigation, naming, and test-double cost without isolating real variation.
  Source: [SOLID principles](https://codewiki.com/architecture/solid-principles/)
- Calling every code smell and backlog item technical debt creates a junk drawer that cannot be prioritized.
  Source: [Technical debt](https://codewiki.com/architecture/tech-debt/)
- Do not treat coverage, complexity, or a static analyzer's remediation time as debt value turns tool proxies into business evidence.
  Source: [Technical debt](https://codewiki.com/architecture/tech-debt/)
- Rewriting an entire legacy module because it is hard to understand discards hidden behavior, production feedback, and incremental rollback.
  Source: [Technical debt](https://codewiki.com/architecture/tech-debt/)
- A fixed “debt percentage” makes teams consume capacity on low-value items and can cap necessary remediation during an incident.
  Source: [Technical debt](https://codewiki.com/architecture/tech-debt/)
- Do not assume this is safe: recording deliberate debt in a `TODO` or ticket title without an owner, trigger, or exit evidence turns a short exception into a permanent default.
  Source: [Technical debt](https://codewiki.com/architecture/tech-debt/)
