All posts

Choosing an architecture from nonfunctional requirements: comparisons and ADRs

· 9 min read

Turn “highly available and scalable” into conditions you can compare. An order system connects SLOs, failure capacity, and operational ownership to mandatory constraints, option comparisons, and an ADR with evidence and review triggers.

Turn a highly available order system into requirements you can evaluate

“We need microservices for growth” and “multiple regions will make it resilient” name solutions before establishing the problem. An architect first aligns the team on user impact and business constraints.

Vague requestComparable conditionValidation
Make it fastAt least 95% of agreed eligible order API requests respond within 500 msMeasure realistic data, skew, and load; observe the same boundary in production
Keep it availableAt least 99.9% success over a 30-day window; timeouts count as failuresFix operation scope, success definition, and measurement point; aggregate the SLI
Survive an AZ failureRemaining application capacity handles peak load after losing one AZTest failure load and recovery, including database failover
Keep it operableAuthorized responders and backups can handle incidents during agreed coverage hoursCheck staffing, runbooks, permissions, and rehearsal results

Define success too. Returning HTTP 200 without saving an order is not successful acceptance. If acceptance and business completion are separate, measure each. Agree exclusions such as authentication errors in advance rather than removing inconvenient failures from the denominator.

Use SLOs to make design and priority decisions

A service level indicator (SLI) measures delivered quality; a service level objective (SLO) sets its target. The Google SRE Workbook describes ratios of good user events and stakeholder agreement as inputs to improvement decisions. CPU utilization alone cannot tell you whether an order succeeded.

For one million eligible requests in 30 days, a 99.9% success target allows an error budget of 1,000 requests: 1,000,000 × (1 − 0.999). This request-based budget cannot simply be converted into downtime minutes. Ten busy minutes and ten quiet minutes affect different numbers of requests.

Track latency separately. Success can meet its target while fewer than 95% of responses finish within 500 ms. Agree who decides between feature work and reliability work as the budget is consumed.

Separate mandatory constraints from preferences before comparing options

Check constraints such as data location, required authorization, and recovery targets first. Low cost cannot offset missing authorization. An untested condition remains pending rather than passing by assumption.

OptionAssessment in this exampleValidate before adoption
Application and database in one AZCannot continue there after losing the AZ; fails this failure requirementIf changing the requirement, agree business impact and recovery time again
Multiple application AZs and a managed database with multi-AZ supportCandidate for validation; delegates some database operationsFailover behavior, reconnection, capacity, restore procedure, and cost
Accept writes in multiple regionsAn option for broader failures; need and operability still require assessmentConflicts, replication, authorization, incident decisions, drills, and operating cost

Use the same cost boundary. Comparing managed database fees only with self-hosted server bills omits upgrades, backups, and recovery drills. Managed services still leave application reconnection and migration work with your team. Include export, schema conversion, and parallel operation when estimating exit effort.

Test the riskiest assumption first

A multi-AZ diagram does not prove failure capacity. With application load evenly spread across three AZs, losing one raises load in each survivor by 1.5 times. A total of 200 requests per second means about 66.7 per AZ normally and 100 per surviving AZ after failure.

Application load per AZ under equal distribution, not measured capacity or latency
  • Normal: three AZs: About 66.7 req/s
  • One AZ lost: two AZs: 100 req/s

This is a first approximation of application traffic. Database write capacity, skew, and failover retries need separate validation. Match data volume, hot keys, and cache state, then measure targets with an AZ unavailable. Do not enter untested performance as a confirmed comparison value.

Record why you chose an option and when to revisit it

An architectural decision record (ADR) captures an important decision's context, choice, and consequences. AWS guidance describes superseding accepted decisions with new ADRs to retain history. Record the constraints at the time rather than declaring every rejected alternative universally inferior.

An ADR before validation: pending tests are not passes
Status: Proposed
Scope: Order acceptance deployment and database operations
Context: Six-person team, peak 200 req/s, one-AZ failure requirement
Options: Single AZ / multi-AZ + managed DB / multi-region writes
Proposal: Multi-AZ + managed DB
Reason: Can test the AZ requirement and delegate some DB operations
Costs: Fees, product dependency, temporary failures during failover
Unknowns: Reconnection, restore time, failure-state p95
Validation: Operations owner tests load, failover, and restoration; business owner reviews
Acceptance: Evidence meets agreed quality, recovery, and operating-cost targets
Review triggers: Location rules, peak load, recovery targets, or staffing change

Five questions for an architecture review

Alongside a diagram, an architect makes the fit between requirements and design open to inspection. When conditions change, the team can reuse the comparison and validation approach to update the decision.

Primary sources for checking design decisions

Tips this post digs into