Software Architecture Solution Architecture / April 17, 2023 / 5 mins read / By Mohamed Bamoh

Quality Attributes: Turning “We Need It Scalable” Into Real Requirements

Most architecture debates are really quality debates

People argue about microservices, databases, messaging, caching.

But those are tools.

Underneath, the real question is almost always this:

What must the system be good at, even when it’s under stress?

That’s what quality attributes are.

They describe how the system should behave, not what it does.

And if you don’t make them explicit, you still end up choosing them. You just choose them by accident.

“Scalable” is not a requirement

“Scalable” is a wish.

A requirement has a shape you can test.

Compare these:

  • “The system should be scalable.”
  • “The system must handle 2,000 checkouts per minute with p95 latency under 300ms.”

Only the second one can guide decisions.

A good quality requirement answers three questions:

1. What scenario are we in? (normal load, peak, partial outage, slow dependency)

2. What do we measure? (latency, error rate, throughput, recovery time)

3. What is acceptable? (a threshold and a time window)

No numbers, no requirement.

Quality attributes are not a long list. They are a ranking.

Teams often collect quality attributes like stickers.

Security. Performance. Reliability. Maintainability. Cost. “And also fast delivery.”

Then everything is “top priority.”

That doesn’t work.

You need a ranking. Because trade-offs are real.

A simple rule:

Pick the top three qualities that define success. Everything else is secondary.

This does two things:

  • It stops endless debates.
  • It gives you a consistent way to say “no.”

Make qualities concrete with scenarios

A good way to turn vague qualities into real ones is to write them as scenarios.

Example: Availability

  • When a single instance dies
  • the system continues serving requests
  • with no user-visible outage
  • and recovers automatically within 60 seconds

Example: Performance

  • Under 10× peak load
  • the checkout API stays under 300ms p95
  • while error rate stays below 0.1%

Example: Deployability

  • A team can deploy one component
  • without coordinating with other teams
  • and roll back in under 5 minutes

Notice what these have in common:

They describe real situations.

That’s the point. Architecture exists to survive reality.

The “hidden qualities” that bite later

Some qualities are loud. Security. Availability. Performance.

Others are quiet. They don’t show up in demos. They show up in year two.

Two that matter almost everywhere: Operability Can we run this system without heroics? Can we detect issues early, understand them, and recover quickly?

Evolvability Can we change the system without fear? Can teams move without stepping on each other?

If you don’t name these early, you will pay for them later. Not in theory. In time. In incidents. In morale.

Quality attributes drive structure

Once qualities are ranked and described, architecture choices become calmer.

Examples:

  • If deployability matters, you avoid tight release trains and shared build-time coupling.
  • If availability matters, you design for failure: timeouts, retries with limits, bulkheads, graceful degradation.
  • If performance matters, you treat latency as a budget and reduce cross-boundary hops.
  • If security matters, you assume hostile networks and design identity, authorization, and auditability from day one.
  • If evolvability matters, you make boundaries real and defend data ownership.

This is why “architecture style” should never be chosen first. Style is a response to qualities and constraints.

A practical method: budgets, not promises

If you want quality requirements to stay real, give them budgets.

  • Latency budget: where time is allowed to be spent
  • Error budget: how much failure is tolerable before you change behavior
  • Dependency budget: how many external calls are acceptable in a critical path

Budgets force honesty.

They also prevent a common failure mode: a system that is “fast” in isolation and slow in production because every request crosses six services and three networks.

Write qualities down like decisions, not aspirations

Quality attributes should live close to decisions, not in a forgotten document.

A useful pattern is to tie each major architectural decision to:

  • the quality it protects
  • the scenario it targets
  • the measurable threshold
  • the consequences you accept

That last part matters.

Every quality comes with a bill.

Example:

If you want high availability, you may accept:

  • more infrastructure
  • more complexity in data consistency
  • more operational rigor

If you want fast delivery, you may accept:

  • less customization
  • stricter conventions
  • opinionated platforms

You don’t avoid trade-offs. You choose them with your eyes open.

Make qualities enforceable, or they decay

A quality requirement that isn’t checked becomes a slogan.

Over time, pressure wins:

  • deadlines
  • shortcuts
  • “just this once”
  • hidden coupling
  • silent performance regressions

So you need guardrails:

  • performance checks in CI for critical paths
  • contract checks for compatibility
  • dependency rules to protect boundaries
  • operational signals that reveal drift

This is not bureaucracy.

It is how you keep architecture aligned while the codebase grows.

Closing

“Scalable” isn’t a requirement. “Secure” isn’t a requirement. “Maintainable” isn’t a requirement.

They are directions.

Your job is to turn directions into something the team can build and verify.

Rank what matters. Describe it as scenarios. Measure it. And keep it alive with guardrails.

That’s how architecture stops being opinion and becomes practice.

Key takeaways / refresher bullets

  • Quality attributes describe how the system must behave under real conditions, not what it does.
  • Vague words (“scalable”, “fast”, “reliable”) must become scenarios + metrics + thresholds.
  • Don’t collect qualities. Rank the top three that define success.
  • Include “quiet” qualities early: operability and evolvability.
  • Let qualities drive structure: boundaries, coupling, data ownership, failure handling.
  • Use budgets (latency/error/dependency) to keep promises honest.
  • Tie major decisions to the qualities they protect, plus the consequences you accept.
  • If you can’t enforce or observe a quality, it will decay under pressure.