Back to System Design Approach & Estimation
Q2Question 2 of 3

Functional vs Non-Functional Requirements

Key Concepts
  • Functional requirements describe what the system does : features, inputs, and outputs testable by a yes-or-no check.
  • Non-functional requirements describe how well it does it : latency, availability, consistency, durability, security, and scalability.
  • Functional requirements map directly to API endpoints and use cases.
  • Non-functional requirements are measured against numeric targets and service level objectives.
  • The four most discussed NFRs in interviews are latency (p99), availability (nines), consistency (strong vs eventual), and scalability (peak QPS).
  • NFRs usually conflict : strong consistency fights availability during a network partition (CAP theorem).
  • For money, favour consistency and durability; for a social feed, favour availability and speed.

Definition

Functional is what the system does; non-functional is how fast, how reliably, and how correctly it does it.
  • Functional requirements : concrete behaviours the system must provide : the features, inputs, and outputs that define what it does, testable by a yes-or-no feature check.
  • Non-functional requirements : quality attributes that constrain how well those behaviours are delivered, such as latency, availability, consistency, durability, security, and scalability.
  • Service level objective (SLO) : a numeric target for a non-functional requirement, such as p99 latency under 200 ms or 99.99% availability.
  • CAP tension : non-functional requirements often conflict, and the designer must make explicit trade-offs aligned with the domain.

When National Bank of India opens a teller counter, the functional requirement is "a customer can withdraw cash." The non-functional requirements are "the withdrawal must complete in under thirty seconds, the counter must be open 99.9% of business hours, and the amount shown must always exactly match the ledger." The first describes what the counter does; the rest describe how good the service must be. A counter that does the right thing slowly, or sometimes, or with wrong numbers, still fails the customer.

Understanding the Concepts

What are functional requirements?

Functional requirements are the features. For a banking transfer system they include "a user can transfer money," "a user can view their balance," "a user can download a statement," and "a user receives a notification after a transfer." Each one is testable with a simple check: did the transfer happen, is the balance shown. You can model them as use cases or user stories, and they map directly to API endpoints.

JAVA
package com.bank.api;

import java.math.BigDecimal;
import java.time.LocalDate;

public interface BankingApi {
    TransferResult transfer(String from, String to, BigDecimal amount);
    BigDecimal balance(String accountId);
    Statement statement(String accountId, LocalDate from, LocalDate to);
}

What are non-functional requirements?

Non-functional requirements are the quality attributes. The four most discussed in interviews are latency, availability, consistency, and scalability. Latency is how fast a single request returns, usually expressed as a percentile like "p99 under 200 milliseconds," meaning 99% of requests are faster than that. Availability is the fraction of time the system is up, expressed in nines, where three nines is about 43 minutes of downtime per month and five nines is about 26 seconds. Consistency is whether every reader sees the latest write. Scalability is whether the system keeps its latency and availability as load grows.

JAVA
package com.bank.design;

public record ServiceLevelObjective(
    long p99LatencyMs,         // e.g. 200 ms
    double availability,       // e.g. 0.9999 (four nines)
    boolean strongConsistency, // true for money
    long targetPeakQps         // e.g. 6000
) {
    public String downtimePerMonth() {
        double downMinutes = (1 - availability) * 30 * 24 * 60;
        return String.format("%.1f minutes/month", downMinutes);
    }
}

How are they different?

Functional requirements are verb-driven and binary : the feature either works or does not. Non-functional requirements are numeric and continuous : the latency is not just "fast" but "p99 under 200 ms." A system can pass every functional test and still fail customers if it is too slow, too often down, or shows stale data.

| Aspect | Functional | Non-Functional |
|---|---|---|
| Describes | What the system does | How well it does it |
| Testable by | Yes/no feature check | Numeric SLO measurement |
| Example | "User can transfer money" | "p99 latency under 200 ms" |
| Maps to | API endpoints, use cases | Architecture decisions, SLOs |

JAVA
package com.bank.design;

public class RequirementTypes {
    // Functional: does the feature exist?
    boolean canTransfer = true;   // yes or no
    boolean canViewBalance = true;

    // Non-functional: how well does it perform?
    long p99LatencyMs = 200;         // numeric target
    double availability = 0.9999;    // four nines
    boolean strongConsistency = true; // domain-driven choice
}

Why do non-functional requirements conflict?

Non-functional requirements usually conflict and force trade-offs. Strong consistency fights availability during a network partition, as the CAP theorem states. Low latency fights durability if you acknowledge writes before they are safely replicated. High availability fights cost because redundant servers and multi-region deployments are expensive.

JAVA
package com.bank.design;

public class NfrConflicts {
    public static void main(String[] args) {
        System.out.println("Conflict                    | Banking resolution");
        System.out.println("----------------------------|----------------------------");
        System.out.println("Consistency vs Availability | Choose consistency (CP)");
        System.out.println("Latency vs Durability       | Accept higher latency");
        System.out.println("Availability vs Cost        | Pay for multi-region");
        System.out.println("Scalability vs Consistency  | Shard carefully by account");
    }
}

How do you write good non-functional requirements?

Write non-functional targets as numbers with units so you can later prove the system met them. Say "p99 transfer latency under 200 ms" instead of "the system should be fast." Say "99.99% availability measured monthly" instead of "the system should be reliable." Vague requirements cannot be tested, monitored, or defended in an interview.

JAVA
package com.bank.design;

public class GoodNfrs {
    // BAD: vague, untestable
    // "The system should be fast and reliable."

    // GOOD: numeric, measurable, domain-aligned
    // "p99 transfer latency < 200 ms"
    // "Monthly availability >= 99.99% (four nines)"
    // "Strong consistency on balance reads (no stale data)"
    // "Peak throughput: 6,000 transfers per second"
}

When should you choose strong consistency vs eventual consistency?

The domain decides. For money you favour consistency and durability even at the cost of some latency, because a wrong balance could allow a double-spend. For a social feed or trending list you favour availability and speed and accept slightly stale data, because a like count being one second behind harms nobody.

JAVA
package com.bank.design;

public class ConsistencyChoice {
    public static String choose(String dataType) {
        return switch (dataType) {
            case "account_balance" -> "STRONG : wrong balance = double-spend risk";
            case "transaction_ledger" -> "STRONG : append-only, audit-critical";
            case "social_feed" -> "EVENTUAL : stale like count is harmless";
            case "analytics_counter" -> "EVENTUAL : approximate is fine";
            default -> "Evaluate per data type";
        };
    }
}

What should a senior engineer emphasize?

A senior engineer treats NFRs as architectural drivers, not afterthoughts. They name which NFR drove each design decision : "I chose PostgreSQL because I need ACID (consistency). I added a cache because I need sub-200ms reads (latency). I deployed across two regions because I need four-nines availability." They also name what they sacrificed : "The cost of strong consistency is higher write latency and reduced availability during partitions."

What are common interview follow-up questions?

Interviewers commonly ask: "Which non-functional requirement drove your database choice?" "What happens to your SLOs during a deployment?" "How would you monitor these NFRs in production?" (dashboards, p99 percentile tracking, uptime SLIs). The ability to connect a requirement to a measurable SLO to a monitoring dashboard is what separates a senior answer from a junior one.

Visual Overview

DIAGRAM
  Functional Requirements          Non-Functional Requirements
  ┌───────────────────────┐        ┌─────────────────────────────┐
  │ What the system DOES  │        │ How WELL it does it         │
  ├───────────────────────┤        ├─────────────────────────────┤
  │ - Transfer money      │        │ - Latency: p99 < 200 ms    │
  │ - View balance        │        │ - Availability: 99.99%     │
  │ - Download statement  │        │ - Consistency: strong (CP) │
  │ - Receive notification│        │ - Scalability: 6K peak QPS │
  └──────────┬────────────┘        └──────────┬──────────────────┘
             │                                │
             ▼                                ▼
  ┌───────────────────────┐        ┌─────────────────────────────┐
  │ Maps to:              │        │ Drives:                     │
  │ API endpoints         │        │ Architecture decisions      │
  │ Use cases             │        │ Database choice (ACID)      │
  │ User stories          │        │ Caching strategy            │
  │ Feature tests         │        │ Replication mode            │
  └───────────────────────┘        │ Sharding strategy           │
                                   │ SLO dashboards              │
                                   └─────────────────────────────┘

  NFR Conflicts (trade-offs the designer must resolve):
  ┌─────────────┐     CAP      ┌──────────────┐
  │ Consistency │◄────────────►│ Availability  │
  └─────────────┘              └──────────────┘
  ┌─────────────┐              ┌──────────────┐
  │ Low Latency │◄────────────►│ Durability   │
  └─────────────┘              └──────────────┘

Key Takeaway

Functional requirements describe what a system does, and non-functional requirements describe how well it does it. The functional requirements are the features themselves, and each one is testable with a simple yes-or-no check. For a banking transfer system the functional requirements are that a customer can transfer money, view their balance, and receive a receipt, and these map directly to API endpoints.

The non-functional requirements are the quality attributes, and in interviews the four I always address are latency, availability, consistency, and scalability. Latency I express as a percentile, such as 99% of transfers completing under 200 milliseconds. Availability I express in nines, where four nines means less than about four minutes of downtime per month. Consistency I decide based on the domain, and for money I always choose strong consistency so the balance shown is never wrong. Scalability I express as a peak QPS target the system must sustain without breaking the other three.

The reason I keep these separate is that a system can pass every functional test and still fail customers completely. A transfer feature that works but takes ten seconds, or is down during salary day, or briefly shows the wrong balance, is a broken banking product even though it technically transfers money. Writing the non-functional targets as concrete numbers is what lets me later prove, with monitoring and dashboards, that the system actually met its promises.

The senior insight I bring is that non-functional requirements conflict and force explicit trade-offs. Strong consistency fights availability during a network partition, and low latency fights durability if I acknowledge a write before it is safely replicated. My job as a designer is to resolve those conflicts in line with the domain. For a banking ledger I favour consistency and durability even at some latency cost, while for a trending-posts feed I would favour availability and speed and accept slightly stale data. Naming those trade-offs out loud is what turns a feature list into a real engineering design.

Remember one sentence: functional requirements say what the system does, non-functional requirements say how well, and the designer's job is to resolve the conflicts between them based on the domain.

---

Share
Use ← → arrow keys to navigate