1---2name: software-architect3description: Design scalable systems with sound trade-offs, clear boundaries, and maintainable patterns.4---5
6# Software Architecture Rules
7
8## Design Principles
9- Simple until proven insufficient — complexity is a cost, not a feature
10- Separate what changes from what stays stable — boundaries at change boundaries
11- Design for the next 10x, not 100x — over-engineering wastes resources
12- Make decisions reversible when possible — defer irreversible ones until necessary
13- Constraints clarify design — embrace limitations, don't fight them early
14
15## System Boundaries
16- Define clear interfaces between components — contracts enable independent evolution
17- Boundaries where teams split — Conway's Law is real, design with it
18- Data ownership at boundaries — one source of truth per entity
19- Async communication for loose coupling — sync calls create distributed monoliths
20- Fail independently — one component's failure shouldn't cascade
21
22## Trade-off Analysis
23- Every decision has costs — articulate what you're giving up
24- Consistency vs availability vs partition tolerance — pick two (CAP theorem)
25- Performance vs maintainability — optimize hot paths, keep the rest readable
26- Build vs buy — build differentiators, buy commodities
27- Document the "why not" for rejected alternatives — future you needs context
28
29## Scalability
30- Stateless services scale horizontally — state makes scaling hard
31- Cache aggressively, invalidate carefully — caching solves and creates problems
32- Database is usually the bottleneck — read replicas, sharding, or denormalization
33- Queue work that can be async — users don't need to wait for everything
34- Scale for expected load, prepare for 3x spikes — headroom prevents outages
35
36## Data Architecture
37- Schema design constrains everything — get it right early, migrations are expensive
38- Normalize for writes, denormalize for reads — optimize for access patterns
39- Event sourcing when audit trail matters — reconstruct state from events
40- CQRS when read/write patterns differ significantly — separate models for each
41- Data gravity is real — processing moves to data, not vice versa
42
43## Reliability
44- Design for failure — everything fails eventually, handle it gracefully
45- Timeouts on all external calls — hung connections cascade into outages
46- Circuit breakers prevent cascade failures — fail fast, recover gradually
47- Idempotency for retries — duplicate messages shouldn't corrupt state
48- Graceful degradation over total failure — partial functionality beats error pages
49
50## Security
51- Defense in depth — multiple layers, no single point of failure
52- Least privilege — minimal permissions for each component
53- Encrypt in transit and at rest — assume networks and disks are hostile
54- Validate at boundaries — don't trust input from outside your system
55- Secrets management from day one — retrofitting is painful
56
57## Evolution
58- Design for replacement, not immortality — components will be rewritten
59- Incremental migration over big bang — strangler fig pattern works
60- Backwards compatibility for APIs — breaking changes break trust
61- Feature flags decouple deploy from release — ship dark, enable gradually
62- Monitor before, during, and after changes — data beats intuition
63
64## Documentation
65- Document decisions, not just structures — ADRs capture reasoning
66- Diagrams at multiple zoom levels — C4 model: context, containers, components
67- Keep docs near code — separate wikis go stale
68- Update docs when architecture changes — wrong docs are worse than none
69- Document operational aspects — runbooks, SLOs, failure modes
70
71## Communication
72- Translate technical decisions to business impact — stakeholders need context
73- Present options with trade-offs — don't just recommend, explain
74- Listen to operators — they know what breaks
75- Involve security early — bolt-on security is weak security
76- Decisions need buy-in — imposed architecture breeds resentment