HomeBlogOtherWhat Are Non-Functional Requirements and Why Should You Audit Them First on Any Project You Inherit?

What Are Non-Functional Requirements and Why Should You Audit Them First on Any Project You Inherit?

September 4, 2026

Oleksandr Sheiko | Software Developer at SDA

Illustration of an NFR audit checklist surrounded by icons for performance, security, reliability, scalability, and cost

Introduction

Functional requirements describe what a system does. Non-functional requirements describe how well it does it - and they're only useful when they're measurable and prioritized. "The system should be fast" is a wish. "p95 under 300 ms at 500 RPS" is a requirement. Trying to maximize every quality at once is the fastest way to end up with none of them.

Here's the thing about non-functional requirements (NFRs): nobody asks for them until they're missing. No client ever wrote "the app must stay up" in a feature list. They just assume it - right up until the Friday evening when it doesn't, and suddenly uptime is the only thing anyone wants to talk about.

In this article we'll walk through what NFRs actually are, why they fail later but cost more than functional ones, how to make them measurable instead of decorative, and how we used an NFR audit as literally the first stage of onboarding onto an inherited codebase - before touching a single line of code. That audit ended up producing the entire improvement roadmap for the next year, so we'd argue it was the highest-leverage two weeks on the whole project.

What are non-functional requirements, exactly?

The standard split goes like this:

  • Functional requirements (FR) - what the system does. "A user can upload a document." "An admin can export a report." You can point at a feature and say "there it is."
  • Non-functional requirements (NFR) - how well it does it. How fast the upload is, how many users can do it at once, what happens when the storage service is down, whether a new developer can find the upload code without a guided tour.

The canonical classification lives in ISO/IEC 25010, the software product quality model (it replaced the older ISO 9126 back in 2011). You don't need to memorize the standard, but the categories are a solid checklist:

  • Performance - latency, throughput, resource usage
  • Availability / reliability - uptime, failure recovery, data durability
  • Scalability - what happens when load grows 10x
  • Security - authn/authz, data protection, attack surface
  • Maintainability - how expensive it is to change the code
  • Observability - can you tell what the system is doing right now
  • Usability - can real users get things done without a manual
  • Compliance - GDPR and friends; a hard constraint, not a preference, if you work with EU personal data
  • Cost - infrastructure and operational spend. People forget this is an NFR. It is. "Runs under 2k/month" is as real a requirement as any latency target.

One more framing that has helped us a lot: FRs are what the demo shows. NFRs are what the demo hides. Every demo runs on one happy user, a warm cache, and a dataset of twelve rows. Production is none of those things.

Why do NFRs fail later but cost more?

A missed functional requirement is loud and cheap. The button doesn't work, someone files a ticket, you fix it, done. The feedback loop is days.

A missed non-functional requirement is quiet and expensive. The feedback loop is months, and the "feedback" tends to arrive as one of these:

  • The product works fine with 50 users in the pilot, then falls over at 2,000 in the real rollout - and now you're rearchitecting under fire instead of designing calmly
  • Nobody defined maintainability expectations, so three years of "just ship it" produced a codebase where a two-day feature takes three weeks - that's not one incident, that's a permanent tax on everything
  • Security was "we'll get to it," and now getting to it means an audit, a retrofit, and awkward client conversations, at roughly 5-10x what building it in would've cost
  • Observability wasn't a requirement, so the first serious production incident takes two days to diagnose because the system is a black box

There's a pattern here: NFR failures don't create tickets, they create eras. An era of slow delivery. An era of firefighting. And because there's no single ticket, there's no single moment where anyone decides to fix it - the pain just becomes background radiation the team learns to live with.

That's the whole argument for treating NFRs explicitly. Not because a standard says so, but because the implicit version of every NFR is "whatever we accidentally ship."

How do you make an NFR measurable instead of decorative?

Most NFR lists die because they're written as adjectives. "The system should be scalable, secure, and performant." Cool. So is everyone's. That sentence can't be tested, can't be prioritized, and can't be failed - which means it also can't be met.

The fix is boring and it works: every NFR gets a metric and a threshold.

DecorativeMeasurable
"Should be fast""p95 API response under 300 ms at 500 RPS"
"Should be reliable""99.9% monthly uptime; recovery from a node failure under 5 minutes"
"Should be maintainable""A new developer ships a meaningful task within 2 weeks of onboarding"
"Should handle growth""Handles 10x current document volume without architecture changes"
"Should be observable""Any 5xx spike is traceable to a root cause from logs/traces within 30 minutes"

A useful trick from the architecture world is the quality attribute scenario: stimulus β†’ environment β†’ measurable response. Not "resilient to failures" but "when the external document API times out (stimulus) during business hours (environment), users see a cached version and a retry completes within 15 minutes (response)." Suddenly you can write a test for it. Or at least an alert.

And if you run production services, you've already met this idea wearing a different badge: SLIs and SLOs are just NFRs that grew up and got jobs. An SLO is a measurable NFR with a consequence attached. If your team has SLOs but "no NFRs," you have NFRs - you just only wrote down the availability ones.

Why can't you just maximize everything?

Because the categories fight each other, and pretending they don't is how you get gold-plating.

  • Performance vs cost - sub-100ms everywhere is achievable; so is the invoice
  • Security vs usability - every additional auth step is friction; the right amount depends on what you're protecting
  • Flexibility vs simplicity - the config-driven, plugin-ready, everything-abstracted design is also the one nobody can debug
  • Availability vs delivery speed - each extra nine of uptime costs more than the previous one, in both infra and process

So the real work isn't listing NFRs - it's ranking them. Pick the 3-4 categories that are actually critical for this system at this stage, set real targets there, and consciously accept "good enough" everywhere else. An internal admin tool used by six people does not need 99.99% uptime, and spending effort there is stealing it from something that matters.

This is also exactly where NFRs connect to Architecture Decision Records, which we covered in a previous article. Look at the Context and Constraints sections of any decent ADR - they're full of NFRs. "We chose the boring queue because ops simplicity beats throughput for a 5-person team" is an NFR trade-off, recorded. Prioritized NFRs upstream make ADRs downstream almost write themselves, because the criteria for every decision are already agreed on.

What do NFRs give the business side?

If you only pitch NFRs as an engineering hygiene thing, they'll get deprioritized every sprint forever. The stronger pitch is that NFRs are the contract language between engineering and everyone else.

1. They turn vague risk into numbers you can argue about. "We have scalability concerns" gets a shrug. "At the current growth rate we hit the database write ceiling in about 5 months, and fixing it after that happens means a freeze on feature work" gets a meeting. Same fact, different language.

2. They price the retrofit honestly. Adding security, scalability, or observability after the fact routinely costs several times what building it in would have - plus it always lands at the worst moment, because the trigger is an incident or a lost deal. NFRs are how you schedule that spend on your terms instead of the incident's.

3. They feed straight into SLAs. If clients sign contracts with uptime or response-time commitments, those numbers have to come from somewhere. Either they come from your NFRs and capacity data, or they come from sales optimism. One of these ends in penalty clauses.

4. They protect delivery speed - which is the metric business actually feels. Maintainability is the NFR with no dashboard, but it's the one stakeholders experience most directly: it's the difference between "that'll take three days" and "that'll take three weeks" for the same request. When velocity drops 30-40% over a couple of years, that's usually not the team getting worse. That's an unmanaged maintainability requirement collecting its tax.

The framing that works with stakeholders: functional requirements are what you're selling, non-functional requirements are whether you'll still be able to sell it in two years.

Which NFR categories matter, and what does failure look like for each?

The eight ISO/IEC 25010-style non-functional requirement categories: performance, availability, scalability, security, maintainability, observability, compliance, and cost, each with its guiding question and failure mode
CategoryQuestion it answersExample of a measurable requirementWhat failure looks like in production
PerformanceIs it fast enough under real load?p95 under 300 ms at 500 RPSUsers double-click everything; conversion drops on slow pages
Availability / reliabilityDoes it stay up, and does it recover?99.9% monthly; recovery under 5 minWeekend incidents; clients asking for an SLA you can't sign
ScalabilityWhat breaks at 10x?10x data volume without architecture changeGreat pilot, disastrous rollout
SecurityWho can do what, to which data?All access role-scoped; secrets rotated; audit trail on sensitive opsBreach, or failing a client's security review
MaintainabilityHow expensive is change?New dev ships a real task within 2 weeksSimple features take weeks; nobody dares touch module X
ObservabilityDo you know what it's doing right now?Root cause of a 5xx spike traceable within 30 minTwo-day debugging sessions; "works on my machine" at prod scale
ComplianceAre you legal in your market?GDPR: personal data deletable on request, export on requestFines; blocked enterprise deals
CostCan you afford it at scale?Infra under X/month at Y usersThe success scenario is unprofitable

The last column is the one we'd actually pin on the wall. NFRs feel abstract until you translate each one into its specific flavor of production pain.

Case study: an NFR audit as stage one of onboarding

Same project we've written about before - a property and building management platform for the Danish market. React frontend, Django REST + PostgreSQL backend, integrations with external government APIs. Team of five: 2 backend, 2 frontend, 1 fullstack. The codebase was inherited from a previous team, with close to zero documentation and no reachable original authors.

The tempting move on day one of an inherited project is to start reading code. We deliberately didn't. The first stage of onboarding was a requirements audit - functional and non-functional - because before judging how the system was built, we needed to agree on what it was actually supposed to guarantee.

What we did, roughly two weeks:

  1. Rebuilt the functional map - what the platform does, module by module, from the UI and the API surface. Not from the code. This alone surfaced features nobody was using and one module two stakeholders described completely differently.
  2. Interviewed stakeholders about implicit expectations - what would count as "broken" for them? How long is an acceptable outage? Which data is genuinely sensitive? Nobody had ever written this down; everyone had strong answers when asked.
  3. Scored the current state per NFR category - a simple good / acceptable / bad wall of the ISO-ish categories against reality. No 40-page report; one table the whole team could hold in their heads.
  4. Ranked the gaps by risk and cost - what would hurt most, soonest, and what would fixing it cost.

What the scoring showed (the honest version):

  • Good, leave it alone: raw performance for the actual user base, and the core domain features themselves - the previous team knew the business well, the what was mostly right
  • Bad, top priority: reliability of the external government API integrations (failures were silent and users found out before we did), maintainability (non-obvious logic nobody dared touch - long-time readers will recognize this codebase), and observability (close to none; debugging meant reproducing locally and praying)
  • Consciously deprioritized: scalability beyond ~3x current load - the market size for this product is known and bounded, so engineering for 100x would have been pure gold-plating

What it produced:

  • A prioritized improvement roadmap that the business side agreed to before any refactoring started - because it was framed as risks and costs, not code aesthetics
  • The refactor-don't-rewrite decision itself (the subject of our first article) - the audit showed the functional layer was largely sound and the pain was concentrated in specific non-functional gaps, which is close to the textbook profile for incremental refactoring
  • The first batch of ADRs - the top-ranked NFRs became the explicit decision criteria, so when we later chose a caching strategy for the slow government APIs or a file-delivery approach, "what are we optimizing for" was already settled

The takeaway: the audit cost two weeks and zero lines of code, and it's the reason the following year of work went in the right order. Every improvement we shipped traced back to a named, ranked gap - instead of whatever annoyed the loudest engineer that month. On an inherited project, an NFR audit isn't paperwork before the real work. It is the real work; everything after is execution.

Common mistakes with non-functional requirements

1. Writing adjectives instead of requirements. "Fast, secure, scalable" is a horoscope - it applies to everyone and predicts nothing. No metric, no threshold, no requirement.

2. Listing every ISO category with equal weight. A 9-category list where everything is "high priority" is a list with no priorities. Pick the 3-4 that are critical for this system now; say "good enough" out loud for the rest.

3. Defining NFRs and never measuring them. A latency target with no monitoring behind it is a decoration. If nothing alerts when the threshold is crossed, you don't have a requirement, you have a hope.

4. Gold-plating. 99.99% uptime for an internal tool, encryption schemes nobody asked for, scalability for a market that can't physically produce that load. Every over-met NFR is budget stolen from an under-met one.

5. Treating the list as write-once. NFRs describe the system at a stage. The right targets at 100 users are wrong at 10,000. Revisit them at real milestones - growth jumps, new markets, new contract types.

6. No owner. FRs have product owners; NFRs often have nobody. An unowned requirement loses every single prioritization fight against features.

7. Testing only the functional side. The suite is green, every button works, and the system still dies at 500 concurrent users. If nothing exercises load, failure modes, and recovery, half the requirements are untested by design.

8. Ignoring cost as a category. Teams hit every performance and availability target and quietly build a system whose success scenario loses money. Infrastructure cost is an NFR; treat it like one.

Conclusion

The dividing line for NFRs isn't written vs unwritten - it's owned vs ambient. Every system has non-functional characteristics; the only question is whether they were chosen or whether they just happened.

A working setup looks like this:

  • Every NFR has a metric and a threshold - no adjectives
  • 3-4 categories are ranked as critical for the current stage; the rest are explicitly "good enough"
  • The critical ones are monitored, and crossing a threshold alerts someone specific
  • Cost and compliance sit on the list next to performance, not in a separate universe
  • The list gets revisited at real milestones, not annually out of guilt
  • On inherited projects, the NFR audit happens before the code diving, and its output is the roadmap

Play the long game here. A year in, the teams that ranked their NFRs and the teams that didn't have shipped a similar number of features - that part is survivorship-neutral. The difference is everything around the features: one team knows its limits before hitting them, prices its risks before selling them, and fixes things in the order that matters. The other one finds all of this out live.

Four-step NFR audit process: rebuild the functional map, interview stakeholders, score the current state, and rank gaps, producing an improvement roadmap, a refactor-don't-rewrite decision, and ADRs

FAQ

What are non-functional requirements?

Non-functional requirements (NFRs) define how well a system performs its functions - performance, reliability, security, maintainability, scalability, observability, compliance, and cost - rather than what those functions are. To be useful, each one needs a metric and a threshold.

What's the difference between functional and non-functional requirements?

Functional requirements describe behavior ("a user can upload a document"); non-functional requirements describe qualities of that behavior ("uploads complete in under 5 seconds at 500 concurrent users, and files survive a storage-node failure"). Functional failures show up on the demo; non-functional failures show up in production.

Where does the classification of NFRs come from?

The most widely used model is ISO/IEC 25010, the software product quality model published in 2011, which replaced the older ISO/IEC 9126 standard from 1991. It's best used as a checklist of categories to consider, not as a mandate to optimize all of them.

How do you make non-functional requirements measurable?

Attach a metric and a threshold to each, ideally as a scenario: stimulus, environment, measurable response. "When the external API times out during business hours, users see cached data and a retry completes within 15 minutes" can be tested; "the system is resilient" cannot.

What are examples of non-functional requirements?

p95 API latency under 300 ms at 500 RPS; 99.9% monthly uptime; recovery from node failure under 5 minutes; a new developer shipping a meaningful task within 2 weeks; personal data deletable on request (GDPR); infrastructure cost under a set monthly budget.

NFR vs SLA vs SLO - what's the difference?

An NFR is an internal quality requirement; an SLO is an NFR you formally measure and commit to internally; an SLA is a contractual promise to a client, usually with penalties. Healthy SLAs are derived from NFRs and real capacity data - not the other way around.

Who should define non-functional requirements?

Jointly: engineering knows what's achievable and what it costs, product and business know what failure costs. NFRs defined by engineers alone get ignored; defined by business alone, they get physically impossible.

When should NFRs be defined?

At project start for greenfield work, and as the first stage of onboarding for an inherited system - auditing actual quality against expected quality is the fastest way to build a credible improvement roadmap. Then revisit at real milestones: growth jumps, new markets, new contract commitments.

SHARE YOURIDEASTO MAKE THEMREAL

Feel free to reach out if you want to collaborate with us, or simply have a chat.

Don't like the forms? Drop us a line via email.

contact@sda.company

...or give us a call. πŸ‡ΊπŸ‡Έ +1 929 322 8837 πŸ‡¬πŸ‡§ +44 7700 183718