Software Architecture Best Practices

Tap menu for chapters & tools

Chapter 12

Software Architecture Best Practices

Quality attributes, trade-offs, and standards that survive contact with production

20 min read

Once you lead a team, architecture stops being a personal craft project. You set the bar for how people design, write things down, and change systems under real limits: time, headcount, risk, and the debt already in production. Best practices are not fashion. They are habits that protect quality while you still ship.

Start from quality attributes, not frameworks

Name what must be true before debating tools. Availability, latency, consistency, security, cost, operability, and team cognitive load are design inputs. A cache is not a goal; p99 latency under load is. Kubernetes is not a goal; deployability and recovery are.

  • List the top three quality attributes for the system this quarter.
  • Attach a measurable signal to each (SLO, budget, audit requirement).
  • Reject designs that optimize vanity scale you do not have.

Core practices that scale with teams

  1. Boundaries first: clear module or service ownership, public interfaces, private internals.
  2. Explicit contracts: APIs, events, schemas, and error semantics written down.
  3. Evolutionary change: prefer reversible steps and strangler patterns over big-bang rewrites.
  4. Observability by design: logs, metrics, traces, and correlation IDs as first-class deliverables.
  5. Security and privacy in the path: authn/z, data classification, least privilege, threat notes on sensitive flows.
  6. Test the seams: contract tests, load tests on critical paths, chaos only where it teaches.
  7. Document decisions, not novels: ADRs for choices that will be re-litigated.

Architecture smells leads should catch early

  • Shared databases across team boundaries with no ownership.
  • Chatty synchronous chains with no timeout, bulkhead, or backoff story.
  • Golden path missing: every feature invents a new stack.
  • Undocumented critical path: only one person can debug production.
  • Config and secrets treated as afterthoughts.
  • Unlimited coupling via a utility package everyone imports.
Lead move

In design review, ask: What fails first? Who is paged? What is the rollback? What quality attribute did we optimize, and which did we sacrifice?

Standards without bureaucracy

Publish a short architecture checklist for PRs and design docs: boundaries, data ownership, failure modes, observability, security, cost, and migration plan. Keep it one page. Enforce through review and examples, not a 40-page governance PDF nobody reads.

Best practice is what your team can execute under load, not what looks impressive on a whiteboard.

Tech debt as a portfolio, not a complaint

If you only say “we have debt,” you will lose the funding argument. Frame debt like a portfolio: risk if you ignore it, cost to fix it, and what option it unlocks. Fold paydown into feature work when you can. Save dedicated capacity when debt blocks safety or speed.

  1. Inventory top debt items with owner, user impact, and incident link if any.
  2. Score by risk, frequency, and blast radius, not by engineer annoyance alone.
  3. Propose a quarterly debt budget (e.g. 15-20% capacity) with explicit cuts if skipped.
  4. Prefer strangler and seam fixes over multi-quarter rewrites without milestones.
  5. Celebrate debt retired in demos so the org sees product value, not only cleanup.
Debt conversation template

If we do nothing: risk. If we invest N weeks: outcome and metric. If we only patch: residual risk. Ask stakeholders to choose with eyes open.

Diagrams for this topic

Visual models you can redraw on a whiteboard or in a design review.

Diagram

Quality attributes before tech
  1. 1Name top 3 attributes
  2. 2Make them measurable
  3. 3List tactics
  4. 4Call out sacrifices
  5. 5Record ADR

Diagram

Architecture decision record (ADR)

ADR skeleton

  • Context
  • Decision drivers
  • Options considered
  • Decision
  • Consequences
  • Status / date

Worked examples

Concrete situations: what goes wrong, what to try instead, what changes.

Cache by default

Setting. Latency is high. Someone suggests Redis in front of everything.

Common miss

Add Redis because “we’ll need it.”

Stronger move

Measure p95, find hot path, cache one read model with TTL and invalidation plan, document trade-offs in ADR.

Outcome. Complexity paid only where it earns latency.

Debt as a rant

Setting. Engineers want a quarter rewrite; product only hears “cleanup.”

Common miss

Argue from frustration and elegance.

Stronger move

Present a debt portfolio item: risk if untouched, effort, metric improved, residual risk if deferred.

Outcome. Stakeholders can fund or explicitly accept risk.

Resources specific to this chapter

Go deeper with books, videos, and tools matched to this topic, not a generic dump.

Practice

End-of-chapter drill

Write a one-page debt item: risk if untouched, effort, metric improved, residual risk if deferred.

Hint: Use the templates pack if you want a skeleton.

“We have debt” without risk language does not get funded.

Learn more on this topic

Full resource library