ЁЯПл The SchoolтА║ЁЯПЫя╕П Software ArchitectureтА║ЁЯУУ рдзрдбрд╛ 11 тАФ ADRs рдЖрдгрд┐ trade-off analysis: рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХреЗрдЪреА рдиреЛрдВрджрд╡рд╣реА
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯУУ рдзрдбрд╛ 11 тАФ ADRs рдЖрдгрд┐ trade-off analysis: рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХреЗрдЪреА рдиреЛрдВрджрд╡рд╣реА

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдорд╛рдЧрдЪрд╛: lesson-10-c4 ┬╖ рдкреБрдврдЪрд╛: lesson-12-evolution


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ10, рдЖрдгрд┐ рдХрд╛. Architecture decision record (ADR) рдПрдХ рдирд┐рд░реНрдгрдп рд▓рд┐рд╣реВрди рдареЗрд╡рддреЗ тАФ рддреНрдпрд╛рдЪрд╛ рд╕рдВрджрд░реНрдн, рдХреЗрд▓реЗрд▓реА рдирд┐рд╡рдб рдЖрдгрд┐ рдкрд░рд┐рдгрд╛рдо тАФ рдореНрд╣рдгрдЬреЗ рдкреБрдврдЪреНрдпрд╛ рд╡реНрдпрдХреНрддреАрд▓рд╛ рдЕрдВрджрд╛рдЬ рд▓рд╛рд╡рд╛рд╡рд╛ рд▓рд╛рдЧрдд рдирд╛рд╣реА. рддреЛ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЖрдзреА, рдПрдХ рд╣рд▓рдХреЗ trade-off analysis: weights рдЕрд╕рд▓реЗрд▓реЗ quality-attribute scenarios, рдкреНрд░рддреНрдпреЗрдХ рдкрд░реНрдпрд╛рдпрд╛рд▓рд╛ рдЧреБрдг, рдЖрдгрд┐ рдЙрддреНрддрд░ рдЙрд▓рдЯрд╛рдпрд▓рд╛ weights рдХрд┐рддреА рдмрджрд▓рд╛рд╡реЗ рд▓рд╛рдЧрддреАрд▓ рдпрд╛рдЪреА рддрдкрд╛рд╕рдгреА. Lab рдпрд╛рд▓рд╛ ATAM-lite рдореНрд╣рдгрддреЗ: SEI рдЪреНрдпрд╛ Architecture Tradeoff Analysis Method рдкрд╛рд╕реВрди рдкреНрд░реЗрд░рд┐рдд рдПрдХ рдЫреЛрдЯрд╛ рдЧреБрдгрд╛рдВрдХрди рд╕рд░рд╛рд╡ тАФ рддреА method рд╕реНрд╡рддрдГ рдирд╡реНрд╣реЗ. atam(), flip_weight() рдЖрдгрд┐ adr() arch/models.py рдордзреНрдпреЗ, adr arch/demo.py рдордзреНрдпреЗ. System Design рд╢рд╛рд│реЗрдЪрд╛ cost, trade-offs рдЖрдгрд┐ ADRs рд╡рд░рдЪрд╛ рдзрдбрд╛ рдПрдХ cost model рдЬреЛрдбрддреЛ; рдЗрдереЗ рдЖрдкрдг рд░рдЪрдиреЗрдЪреНрдпрд╛ рдирд┐рд░реНрдгрдпрд╛рд╡рд░ рд▓рдХреНрд╖ рджреЗрддреЛ.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдЕрдиреЗрдХ рд╡рд░реНрд╖рд╛рдВрдкреВрд░реНрд╡реА рдХреЛрдгреАрддрд░реА рдард░рд╡рд▓реЗ рдХреА рд╢рд╛рд│реЗрд▓рд╛ рдЪрд╛рд░ рдирд╡реНрд╣реЗ рддрд░ рдПрдХрдЪ рдЗрдорд╛рд░рдд рдЕрд╕реЗрд▓. рдЖрдЬ рдРрд╢реНрд╡рд░реНрдпрд╛ рд╡рд┐рдЪрд╛рд░рддреЗ: "рдХрд╛? рдЪрд╛рд░ рдЗрдорд╛рд░рддреА рдХрд┐рддреА рдЫрд╛рди рдЭрд╛рд▓реНрдпрд╛ рдЕрд╕рддреНрдпрд╛!" рдХреЛрдгрд╛рд▓рд╛рдЪ рдЖрдард╡рдд рдирд╛рд╣реА. ЁЯд╖тАНтЩАя╕П рдореНрд╣рдгреВрди рд╢рд╛рд│реЗрдд рддреЛрдЪ рд▓рд╛рдВрдмрд▓рдЪрдХ рд╡рд╛рдж рдкреБрдиреНрд╣рд╛ рд╕реБрд░реВ рд╣реЛрддреЛ.

рдХрддрд░рд┐рдирд╛ рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХреЗрдЪреНрдпрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдд рдПрдХ рдиреЛрдВрджрд╡рд╣реА ЁЯУУ рд╕реБрд░реВ рдХрд░рддреЗ. рдкреНрд░рддреНрдпреЗрдХ рдореЛрдареНрдпрд╛ рдирд┐рд░реНрдгрдпрд╛рд╕рд╛рдареА рддреА рдПрдХ рдкрд╛рди рд▓рд┐рд╣рд┐рддреЗ:

рдЖрдгрд┐ рдард░рд╡рдгреНрдпрд╛рдЖрдзреА рддрд┐рдиреЗ рдПрдХ рдЫреЛрдЯрд╛ рддрдХреНрддрд╛ рдХреЗрд▓рд╛: рд╕рд░реНрд╡рд╛рдд рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдХрд╛рдп, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдпреЛрдЬрдирд╛ рдХрд┐рддреА рдЪрд╛рдВрдЧрд▓реА рдард░рддреЗ. рддрд┐рдиреЗ рд╣реЗрд╣реА рд▓рд┐рд╣реВрди рдареЗрд╡рд▓реЗ: "рдЖрдкрд▓реНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рджрд┐рд╡рд╢реА рдкреБрдиреНрд╣рд╛ рдмрд╛рдВрдзрдХрд╛рдо рдХрд░рдгреЗ рдХрдзреА рдЦреВрдк рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЭрд╛рд▓реЗ, рддрд░ рд╣реЗ рдкреБрдиреНрд╣рд╛ рдкрд╛рд╣рд╛." рдЖрддрд╛ рд╡рд╛рдж рдкрд╛рдЪ рдорд┐рдирд┐рдЯрд╛рдВрдд рд╕рдВрдкрддреЛ: рдкрд╛рди рд╡рд╛рдЪрд╛.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    s["ЁЯУЛ 5 scenarios, weights 1тАУ3<br/>modifiability 3 ┬╖ operability 3 ┬╖ performance 2<br/>deployability 1 ┬╖ scalability 1"]
    s --> mm["ЁЯПл modular monolith тЖТ 42"]
    s --> m["ЁЯПЪя╕П monolith тЖТ 35"]
    s --> ms["ЁЯПШя╕П microservices тЖТ 34"]
    mm --> adr["ЁЯУУ ADR-0007: A modular monolith<br/>Status: Accepted"]
    flip["тЪЦя╕П deployability weight 4 тЖТ microservices 49 vs 48"] -.->|"revisit when"| adr

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/software-architecture/lesson-diagrams.html#l11

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рд╕рд░реНрд╡рд╛рдд рдорд╣рд╛рдЧ рдирд┐рд░реНрдгрдп (рдзрдбрд╛ 01) рд╣реЗрдЪ рдЕрд╕реЗ рдирд┐рд░реНрдгрдп рдЕрд╕рддрд╛рдд рдЬреНрдпрд╛рдВрдЪреА рдХрд╛рд░рдгреЗ рд╕рд░реНрд╡рд╛рдд рд▓рд╡рдХрд░ рд╡рд┐рд╕рд░рд▓реА рдЬрд╛рддрд╛рдд. "рдХрд╛" рд╢рд┐рд╡рд╛рдп, рдЯреАрдореНрд╕ рдПрдХрддрд░ рдирд┐рд░реНрдгрдпрд╛рд▓рд╛ рдХрдзреАрдЪ рд╣рд╛рдд рд▓рд╛рд╡рдд рдирд╛рд╣реАрдд (рднреАрддреА) рдХрд┐рдВрд╡рд╛ рддреЛ рдХрд╢рд╛рдЪреЗ рд░рдХреНрд╖рдг рдХрд░рдд рд╣реЛрддрд╛ рд╣реЗ рди рдХрд│рддрд╛ рдЙрд▓рдЯрд╡рддрд╛рдд (рдЙрд▓рдерд╛рдкрд╛рд▓рде). Weighted рддрдХреНрддрд╛ рдЯреАрдорд▓рд╛ рдирд┐рд╡рдб рдХрд░рдгреНрдпрд╛рдЖрдзреА рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдХрд╛рдп рдореМрд▓реНрдпрд╡рд╛рди рд╡рд╛рдЯрддреЗ рддреЗ рд╕рд╛рдВрдЧрд╛рдпрд▓рд╛ рднрд╛рдЧ рдкрд╛рдбрддреЛ, рдЖрдгрд┐ weight check рдирд┐рд░реНрдгрдп рдХрдзреА рдкреБрдиреНрд╣рд╛ рдЙрдШрдбрд╛рд╡рд╛ рд╣реЗ рд╕рд╛рдВрдЧрддреЛ тАФ рддреНрдпрд╛рдореБрд│реЗ "рдПрдХ рджрд┐рд╡рд╕ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ microservices рд▓рд╛рдЧрддреАрд▓ рдХрджрд╛рдЪрд┐рдд" рдпрд╛рдЪреЗ рд░реВрдкрд╛рдВрддрд░ рдареЛрд╕ trigger рдордзреНрдпреЗ рд╣реЛрддреЗ.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

arch/models.py рдордзрд▓реНрдпрд╛ SCENARIOS рдордзреНрдпреЗ 1тАУ3 weights рдЕрд╕рд▓реЗрд▓реЗ рдкрд╛рдЪ scenarios рдЖрд╣реЗрдд; OPTIONS рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ рдкрд░реНрдпрд╛рдпрд╛рдЪреЗ 1тАУ5 scores рддреНрдпрд╛рдЪ рдХреНрд░рдорд╛рдиреЗ рдЖрд╣реЗрдд. atam(options, scenarios, weights) weight ├Ч score рдЪреА рдмреЗрд░реАрдЬ рдХрд░рддреЗ. flip_weight(attr, rival) рдПрдХрд╛ attribute рдЪреЗ weight 1 рдкрд╛рд╕реВрди рд╡рд░ рд╡рд╛рдврд╡рддреЗ рдЖрдгрд┐ рдЬреНрдпрд╛ рдкрд╣рд┐рд▓реНрдпрд╛ weight рд▓рд╛ rival рд▓рд╛ рд╕рд░реНрд╡рд╛рдзрд┐рдХ рдЧреБрдг рдорд┐рд│рддрд╛рдд рддреЗ рдкрд░рдд рдХрд░рддреЗ (рдХрд┐рдВрд╡рд╛ None). adr(number, title, context, decision, consequences) Nygard рд╢реИрд▓реАрдЪрд╛ ADR Markdown рдордзреНрдпреЗ рдкрд░рдд рдХрд░рддреЗ.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 arch/demo.py adr
python3 - <<'EOF'
import sys; sys.path.insert(0, "arch"); from models import atam, SCENARIOS, adr
base = [s[2] for s in SCENARIOS]
for w in (1, 2, 3, 4, 5):
    t = atam(weights=base[:3] + [w] + base[4:])
    print(f"deployability weight {w}: " + " ┬╖ ".join(f"{o} {v}" for o, v in t.items()) + f" тЖТ {max(t, key=t.get)}")
print(adr(7, "A modular monolith for the school app", "4 departments, a team of 3, results-day peaks.",
          "One deployable, departments as modules, boundaries checked in CI.", ["one transaction per request", "no independent deploys yet"]))
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

adr рд╣реЗ рдЫрд╛рдкрддреЗ:

   modular monolith [4, 5, 5, 2, 3] тЖТ 42
   monolith         [2, 5, 5, 1, 3] тЖТ 35
   microservices    [4, 2, 3, 5, 5] тЖТ 34
   weights matter: microservices would win if deployability weighed 4 (not 1), or scalability 6 (not 1)

рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:

deployability weight 1: monolith 35 ┬╖ modular monolith 42 ┬╖ microservices 34 тЖТ modular monolith
deployability weight 2: monolith 36 ┬╖ modular monolith 44 ┬╖ microservices 39 тЖТ modular monolith
deployability weight 3: monolith 37 ┬╖ modular monolith 46 ┬╖ microservices 44 тЖТ modular monolith
deployability weight 4: monolith 38 ┬╖ modular monolith 48 ┬╖ microservices 49 тЖТ microservices
deployability weight 5: monolith 39 ┬╖ modular monolith 50 ┬╖ microservices 54 тЖТ microservices
# ADR-0007: A modular monolith for the school app

Status: Accepted

## Context
4 departments, a team of 3, results-day peaks.

## Decision
One deployable, departments as modules, boundaries checked in CI.

## Consequences
- one transaction per request
- no independent deploys yet

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдЖрдЬрдЪреНрдпрд╛ weights рдиреБрд╕рд╛рд░ modular monolith рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдЬрд┐рдВрдХрддреЛ (42 рд╡рд┐рд░реБрджреНрдз 35 рд╡рд┐рд░реБрджреНрдз 34). рдкрдг рдЙрддреНрддрд░ рдард░рд▓реЗрд▓реЗ рдирд╛рд╣реА: рдЗрддрд░ рд╡рд┐рднрд╛рдЧрд╛рдВрд╢рд┐рд╡рд╛рдп рдПрдХрдЪ рд╡рд┐рднрд╛рдЧ release рдХрд░рдгреНрдпрд╛рдЪреЗ рдореВрд▓реНрдп 1 рдРрд╡рдЬреА 4 рдЭрд╛рд▓реЗ, рддрд░ microservices рдлрдХреНрдд рдПрдХрд╛ рдЧреБрдгрд╛рдиреЗ рдЬрд┐рдВрдХрддреАрд▓ (49 рд╡рд┐рд░реБрджреНрдз 48). рдпрд╛рддреВрди рджреЛрди рдЧреЛрд╖реНрдЯреА рдХрд│рддрд╛рдд. рдкрд╣рд┐рд▓реА, рдирд┐рд░реНрдгрдп рдмрд▒реНрдпрд╛рдкреИрдХреА рднрдХреНрдХрдо рдЖрд╣реЗ тАФ рддреЛ рдЙрд▓рдЯрдгреНрдпрд╛рдЖрдзреА deployability, modifiability рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдорд╣рддреНрддреНрд╡рд╛рдЪреА рд╡реНрд╣рд╛рдпрд▓рд╛ рд╣рд╡реА. рджреБрд╕рд░реА, рдХрд╢рд╛рд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡рд╛рдпрдЪреЗ рддреЗ рдХрд│рддреЗ: ADR рдЪреЗ consequences рд╕рд╛рдВрдЧрддрд╛рдд "deployability weight 4 рдЭрд╛рд▓реЗ рддрд░ рдкреБрдиреНрд╣рд╛ рдкрд╛рд╣рд╛", рдореНрд╣рдгреВрди рднрд╡рд┐рд╖реНрдпрд╛рддреАрд▓ рдЯреАрдорд▓рд╛ рдЖрд╡рдбреА-рдирд┐рд╡рдбреАрд╡рд░ рдкреБрдиреНрд╣рд╛ рд╡рд╛рдж рдШрд╛рд▓рдгреНрдпрд╛рдРрд╡рдЬреА trigger рдорд╛рд╣реАрдд рдЕрд╕рддреЛ. рдпрд╛рдкреИрдХреА рдХреЛрдгрддреНрдпрд╛рд╣реА weight рд▓рд╛ monolith рдХрдзреАрдЪ рдЬрд┐рдВрдХрдд рдирд╛рд╣реА тАФ рд╡рд┐рднрд╛рдЧрд╛рдВрдордзрд▓реНрдпрд╛ рднрд┐рдВрддреА (modifiability 4 рд╡рд┐рд░реБрджреНрдз 2) рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рд░рдЦреНрдпрд╛ рдЖрд╣реЗрдд.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд

рдЦрд▒реНрдпрд╛ project рд╡рд░ тАФ Nat Pryce рдпрд╛рдВрдЪреЗ adr-tools ADRs рдХреНрд░рдорд╛рдВрдХ рджрд┐рд▓реЗрд▓реНрдпрд╛ Markdown files рдореНрд╣рдгреВрди рдареЗрд╡рддреЗ:

adr init docs/architecture/decisions          # creates 0001-record-architecture-decisions.md
adr new A modular monolith for the school app # 0002-a-modular-monolith-for-the-school-app.md
adr new -s 2 Split grades into its own service   # a new ADR that supersedes 0002
adr list

Nygard рд╢реИрд▓реАрдЪрд╛ ADR, repo рдордзрд▓реА file рдореНрд╣рдгреВрди:

# 7. A modular monolith for the school app

Date: 2026-09-01

## Status
Accepted

## Context
Four departments (admissions, grades, fees, timetable), a team of three, a 20├Ч spike on
results day. Scored: modular monolith 42, monolith 35, microservices 34.

## Decision
One deployable. Departments are top-level packages. import-linter contracts keep them apart.

## Consequences
- One database transaction per request; no sagas.
- No independent deploys: a fees change redeploys grades.
- Revisit if independent deployability becomes as important as modifiability.

рдЗрддрд░ рд▓реЛрдХрдкреНрд░рд┐рдп templates рдореНрд╣рдгрдЬреЗ MADR (Markdown Any Decision Records), рдЬреЛ рдлрд╛рдпрджреЗ-рддреЛрдЯреНрдпрд╛рдВрд╕рд╣ "considered options" рдЬреЛрдбрддреЛ, рдЖрдгрд┐ Y-statements ("In the context of тАж, facing тАж, we decided тАж to achieve тАж, accepting тАж").

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рддреБрдордЪреА рдЯреАрдо рдЬреНрдпрд╛ рдирд┐рд░реНрдгрдпрд╛рд╡рд░ рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рд╡реЗрд│рд╛ рдкреБрдиреНрд╣рд╛ рд╡рд╛рдж рдШрд╛рд▓рддреЗ рддреЛ рд╢реЛрдзрд╛. рдпрд╛ рдЖрдард╡рдбреНрдпрд╛рдд рддреНрдпрд╛рдЪрд╛ ADR рд▓рд┐рд╣рд╛, рдкреБрдиреНрд╣рд╛ рдкрд╛рд╣рдгреНрдпрд╛рдЪреНрдпрд╛ trigger рд╕рд╣ тАФ рдЖрдгрд┐ рддреЛ рдЬреНрдпрд╛ code рд▓рд╛ рд▓рд╛рдЧреВ рд╣реЛрддреЛ рддрд┐рдереВрди рддреНрдпрд╛рдЪреА link рджреНрдпрд╛.

тПня╕П рдкреБрдвреЗ

рдирд┐рд░реНрдгрдп рдШреЗрддрд▓реЗ, рдирд┐рдпрдо рддрдкрд╛рд╕рд▓реЗ, рдЪрд┐рддреНрд░реЗ рдЦрд░реА. рдкрдг рд╢рд╛рд│рд╛ рдкреНрд░рддреНрдпреЗрдХ term рд▓рд╛ рд╡рд╛рдврддреЗ. рдореБрд▓реЗ рдЖрдд рдЕрд╕рддрд╛рдирд╛ рдЗрдорд╛рд░рдд рдХрд╢реА рдмрджрд▓рд╛рдпрдЪреА? Evolving architecture тАФ рдЖрдгрд┐ рд╕рдВрдкреВрд░реНрдг рдЪрд┐рддреНрд░.

git checkout lesson-12-evolution

ЁЯУУ Lesson 11 тАФ ADRs and trade-off analysis: the principal's logbook

ЁЯУН You are here: Lesson 11 of 12 ┬╖ Previous: lesson-10-c4 ┬╖ Next: lesson-12-evolution


ЁЯУж What's in this branch

Lessons 01тАУ10, plus the why. An architecture decision record (ADR) writes down one decision тАФ its context, the choice and the consequences тАФ so the next person does not have to guess. Before writing it, a light trade-off analysis: quality-attribute scenarios with weights, each option scored, and a check of how much the weights would have to change to flip the answer. The lab calls it ATAM-lite: a small scoring exercise inspired by the SEI's Architecture Tradeoff Analysis Method тАФ not the method itself. atam(), flip_weight() and adr() in arch/models.py, adr in arch/demo.py. The System Design school's lesson on cost, trade-offs and ADRs adds a cost model; here we focus on the structure decision.

ЁЯзТ Explain like I'm 5

Years ago, someone decided the school would have one building, not four. Today, Aishwarya asks: "Why? Four buildings would be so nice!" Nobody remembers. ЁЯд╖тАНтЩАя╕П So the school has the same long argument all over again.

Katrina starts a logbook ЁЯУУ in the principal's office. For every big decision she writes one page:

And before deciding, she made a small table: what matters most, and how well each plan does. She even wrote down: "if rebuilding on your own day ever becomes very important, look at this again." Now the argument takes five minutes: read the page.

ЁЯЧ║я╕П Diagram

flowchart LR
    s["ЁЯУЛ 5 scenarios, weights 1тАУ3<br/>modifiability 3 ┬╖ operability 3 ┬╖ performance 2<br/>deployability 1 ┬╖ scalability 1"]
    s --> mm["ЁЯПл modular monolith тЖТ 42"]
    s --> m["ЁЯПЪя╕П monolith тЖТ 35"]
    s --> ms["ЁЯПШя╕П microservices тЖТ 34"]
    mm --> adr["ЁЯУУ ADR-0007: A modular monolith<br/>Status: Accepted"]
    flip["тЪЦя╕П deployability weight 4 тЖТ microservices 49 vs 48"] -.->|"revisit when"| adr

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/software-architecture/lesson-diagrams.html#l11

тЭУ What

ЁЯдФ Why

Because the most expensive decisions (lesson 01) are also the ones whose reasons are forgotten fastest. Without the why, teams either never touch a decision (fear) or undo it without knowing what it protected (churn). A weighted table forces the team to say what it values before it picks, and the weight check says when the decision should be reopened тАФ which turns "we might need microservices one day" into a concrete trigger.

ЁЯФз How (in this repo)

SCENARIOS in arch/models.py holds five scenarios with weights 1тАУ3; OPTIONS holds each option's scores 1тАУ5 in the same order. atam(options, scenarios, weights) sums weight ├Ч score. flip_weight(attr, rival) raises one attribute's weight from 1 upward and returns the first weight at which rival scores highest (or None). adr(number, title, context, decision, consequences) returns a Nygard-style ADR as Markdown.

ЁЯзк Try it

python3 arch/demo.py adr
python3 - <<'EOF'
import sys; sys.path.insert(0, "arch"); from models import atam, SCENARIOS, adr
base = [s[2] for s in SCENARIOS]
for w in (1, 2, 3, 4, 5):
    t = atam(weights=base[:3] + [w] + base[4:])
    print(f"deployability weight {w}: " + " ┬╖ ".join(f"{o} {v}" for o, v in t.items()) + f" тЖТ {max(t, key=t.get)}")
print(adr(7, "A modular monolith for the school app", "4 departments, a team of 3, results-day peaks.",
          "One deployable, departments as modules, boundaries checked in CI.", ["one transaction per request", "no independent deploys yet"]))
EOF

тЬЕ Verify тАФ what you should see

adr prints:

   modular monolith [4, 5, 5, 2, 3] тЖТ 42
   monolith         [2, 5, 5, 1, 3] тЖТ 35
   microservices    [4, 2, 3, 5, 5] тЖТ 34
   weights matter: microservices would win if deployability weighed 4 (not 1), or scalability 6 (not 1)

Your snippet prints:

deployability weight 1: monolith 35 ┬╖ modular monolith 42 ┬╖ microservices 34 тЖТ modular monolith
deployability weight 2: monolith 36 ┬╖ modular monolith 44 ┬╖ microservices 39 тЖТ modular monolith
deployability weight 3: monolith 37 ┬╖ modular monolith 46 ┬╖ microservices 44 тЖТ modular monolith
deployability weight 4: monolith 38 ┬╖ modular monolith 48 ┬╖ microservices 49 тЖТ microservices
deployability weight 5: monolith 39 ┬╖ modular monolith 50 ┬╖ microservices 54 тЖТ microservices
# ADR-0007: A modular monolith for the school app

Status: Accepted

## Context
4 departments, a team of 3, results-day peaks.

## Decision
One deployable, departments as modules, boundaries checked in CI.

## Consequences
- one transaction per request
- no independent deploys yet

ЁЯПБ What you just proved

With today's weights the modular monolith wins clearly (42 vs 35 vs 34). But the answer is not fixed: if releasing one department without the others became worth 4 instead of 1, microservices would win by a single point (49 vs 48). That tells you two things. First, the decision is reasonably robust тАФ deployability must become more important than modifiability before it flips. Second, it tells you what to watch: the ADR's consequences say "revisit if deployability weight reaches 4", so a future team knows the trigger instead of re-arguing taste. The monolith never wins at any of these weights тАФ the walls between departments (modifiability 4 vs 2) are worth having.

тЪая╕П Common mistakes

ЁЯПн In production

On a real project тАФ Nat Pryce's adr-tools keeps ADRs as numbered Markdown files:

adr init docs/architecture/decisions          # creates 0001-record-architecture-decisions.md
adr new A modular monolith for the school app # 0002-a-modular-monolith-for-the-school-app.md
adr new -s 2 Split grades into its own service   # a new ADR that supersedes 0002
adr list

A Nygard-style ADR, as a file in the repo:

# 7. A modular monolith for the school app

Date: 2026-09-01

## Status
Accepted

## Context
Four departments (admissions, grades, fees, timetable), a team of three, a 20├Ч spike on
results day. Scored: modular monolith 42, monolith 35, microservices 34.

## Decision
One deployable. Departments are top-level packages. import-linter contracts keep them apart.

## Consequences
- One database transaction per request; no sagas.
- No independent deploys: a fees change redeploys grades.
- Revisit if independent deployability becomes as important as modifiability.

Other popular templates are MADR (Markdown Any Decision Records), which adds "considered options" with pros and cons, and Y-statements ("In the context of тАж, facing тАж, we decided тАж to achieve тАж, accepting тАж").

ЁЯПн Why this matters in production: find the decision your team re-argues most often. Write its ADR this week, including the trigger for revisiting it тАФ and link it from the code it governs.

тПня╕П Next

Decisions made, rules checked, drawings true. But a school grows every term. How do you change a building while children are inside? Evolving architecture тАФ and the whole picture.

git checkout lesson-12-evolution
тЖР Previousc4Next тЖТevolution

This page is the lesson's README from the lesson-11-adrs branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.