Functional vs. Non-Functional Requirements: What Every System Designer Should Know
Every system design starts with requirements. They come in two kinds: functional requirements, which describe what the system should do, and non-functional requirements, which describe how well it should do it. Getting both right is the difference between a system that merely works on a demo day and one that stays fast, secure and reliable for real users.
This tutorial explains both types in simple terms, shows how to write them clearly, compares them side by side, applies them to a real example, and shows how each type appears in Java code.
1. Functional Requirements
Functional requirements describe the specific behaviour of a system: the features, calculations, data handling and interactions it must support. They define what the system should do.
- A user should be able to log in using an email and password.
- The system should allow users to place an order online.
- The application should generate monthly sales reports automatically.
- An admin should be able to deactivate a user account.
- The system should send an email when an order is shipped.
Functional requirements are usually written as features or user stories, for example: "As a customer, I want to track my order so that I know when it will arrive." They are either met or not met, which makes them easy to test.
2. Non-Functional Requirements
Non-functional requirements (NFRs) describe the quality attributes of a system. They focus on how the system performs its functions, rather than what the functions are.
- The home page should load within 2 seconds for 95% of requests.
- The application should be available 99.9% of the time each month.
- All personal data should be encrypted in transit and at rest.
- The system should support 10,000 users online at the same time.
- The checkout page should meet WCAG 2.1 AA accessibility guidelines.
NFRs are sometimes called quality attributes, system qualities or "-ilities" (scalability, availability, reliability, maintainability). They ensure the system is fast, reliable, secure and usable.
3. Common Types of Non-Functional Requirements
| Type | Question It Answers | Example Requirement |
|---|---|---|
| Performance | How fast is it? | Search returns results in under 300 ms at p95 |
| Scalability | Can it grow? | Handle 5x today's traffic by adding servers, with no code changes |
| Availability | Is it up when needed? | 99.95% monthly uptime |
| Reliability | Does it work correctly without failing? | Fewer than 0.1% of payments fail because of system errors |
| Security | Is it protected? | Passwords hashed with bcrypt; all traffic over HTTPS |
| Usability | Is it easy to use? | A new user can place an order in under 3 minutes |
| Maintainability | Is it easy to change? | A typical bug fix can be released within one day |
| Observability | Can we see what is happening? | Every request has a trace ID in logs and metrics |
| Durability | Is data safe from loss? | Daily backups kept for 30 days; data loss no more than 5 minutes |
| Compliance | Does it follow the rules? | Personal data handled according to GDPR |
| Portability | Can it run elsewhere? | Runs on any cloud that supports Kubernetes |
| Cost | Is it affordable? | Infrastructure cost below $0.01 per order |
Learn more about individual qualities in Availability, Latency, Throughput and Scalability.
4. Key Differences
| Aspect | Functional Requirements | Non-Functional Requirements |
|---|---|---|
| Definition | What the system should do | How well the system should do it |
| Focus | Features, actions, business rules | Performance, security, reliability, usability |
| Example | User login, payment processing | Response time, uptime, scalability |
| Measurement | Yes/No: the feature works or it does not | Numbers: seconds, percentages, requests per second |
| Testing | Unit, integration and acceptance tests | Load, stress, security and chaos tests |
| Defined by | Business users, product owners | Architects and engineers, with the business |
| If missing | A feature is absent | The system may be slow, unsafe or keep crashing |
| Effect on design | Shapes components, APIs and data | Shapes architecture, infrastructure and technology choices |
5. How to Write Good Requirements
A useful requirement is clear, specific and testable. Vague requirements cause arguments later, because nobody can prove whether they were met.
| Vague (Avoid) | Clear and Testable (Prefer) |
|---|---|
| "The system should be fast." | "The product page loads in under 1.5 seconds for 95% of requests at 2,000 requests per second." |
| "The system should always be available." | "The ordering service is available 99.9% of the time each calendar month." |
| "The system should be secure." | "All APIs require a valid OAuth 2.0 token, and failed logins are limited to 5 per minute." |
| "Users can search." | "Users can search products by name, category and price range, sorted by relevance." |
A good checklist is SMART: Specific, Measurable, Achievable, Relevant and Testable. For NFRs, always state the metric, the target and the conditions (for example, "at peak load").
6. Example: A Food Delivery App
Functional Requirements
- Customers can browse restaurants near their location.
- Customers can add dishes to a cart and place an order.
- Customers can pay by card or digital wallet.
- Restaurants can accept or reject incoming orders.
- Delivery partners can see assigned orders and update their status.
- Customers can track the delivery on a live map.
- Customers can rate the restaurant and the delivery.
Non-Functional Requirements
- Performance: restaurant search responds in under 500 ms at p95.
- Scalability: support 50,000 orders per hour at lunch and dinner peaks.
- Availability: ordering and payment are available 99.95% of the time.
- Reliability: no order is lost or charged twice, even if a service restarts.
- Security: card data is handled only by a PCI DSS compliant payment provider.
- Freshness: the driver's location on the map is no more than 10 seconds old.
- Usability: the app works on phones with slow 3G connections.
7. How Requirements Shape the Design
Functional requirements tell you which components to build. Non-functional requirements usually decide how to build them, and they drive most of the big architecture choices:
| Requirement | Design Decision It Leads To |
|---|---|
| Search under 500 ms at p95 | Dedicated search engine and a cache for popular restaurants |
| 50,000 orders per hour at peak | Stateless services, horizontal scaling and a message queue for spikes |
| 99.95% availability | Multiple instances across availability zones, health checks and failover |
| No order charged twice | Idempotency keys on payments and the transactional outbox pattern |
| Location no older than 10 seconds | WebSockets or push updates instead of slow polling |
| Card data handled securely | Hosted payment pages from a certified provider; no card storage |
Two systems with the same functional requirements can look completely different if their NFRs differ. A bookstore for 100 users and one for 100 million users have the same features but very different architectures.
8. Requirements in Java Code
A Functional Requirement as Code and Test
Requirement: "An order can be placed only if every item is in stock; the total is the sum of item prices times quantities."
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
public class OrderService {
public record OrderLine(String productId, int quantity, BigDecimal unitPrice) {
}
private final Map<String, Integer> stock;
public OrderService(Map<String, Integer> stock) {
this.stock = stock;
}
public BigDecimal placeOrder(List<OrderLine> lines) {
for (OrderLine line : lines) {
int available = stock.getOrDefault(line.productId(), 0);
if (available < line.quantity()) {
throw new IllegalStateException("Out of stock: " + line.productId());
}
}
return lines.stream()
.map(line -> line.unitPrice().multiply(BigDecimal.valueOf(line.quantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
class OrderServiceTest {
private final OrderService service = new OrderService(Map.of("pizza", 5, "cola", 0));
@Test
void calculatesTotalWhenItemsAreInStock() {
BigDecimal total = service.placeOrder(List.of(
new OrderService.OrderLine("pizza", 2, new BigDecimal("9.50"))));
assertEquals(new BigDecimal("19.00"), total); // functional: yes or no
}
@Test
void rejectsOrderWhenItemIsOutOfStock() {
assertThrows(IllegalStateException.class, () -> service.placeOrder(List.of(
new OrderService.OrderLine("cola", 1, new BigDecimal("1.50")))));
}
}
Functional requirements map directly to business logic and are verified by tests that pass or fail.
Checking a Non-Functional Requirement
Requirement: "95% of search requests finish in under 300 ms." NFRs are checked with numbers. This program calculates the 95th percentile (p95) of measured response times and compares it to the target:
import java.util.Arrays;
public class LatencyRequirementCheck {
private static final long TARGET_P95_MILLIS = 300;
/** Returns the value below which the given percentage of samples fall. */
static long percentile(long[] samples, double percent) {
long[] sorted = samples.clone();
Arrays.sort(sorted);
int index = (int) Math.ceil(percent / 100.0 * sorted.length) - 1;
return sorted[Math.max(0, index)];
}
public static void main(String[] args) {
// Response times (ms) of 20 search requests, e.g. collected during a load test
long[] latencies = {120, 95, 180, 210, 140, 160, 250, 130, 110, 175,
190, 205, 145, 170, 230, 260, 280, 150, 610, 640};
long p50 = percentile(latencies, 50);
long p95 = percentile(latencies, 95);
System.out.println("p50 = " + p50 + " ms");
System.out.println("p95 = " + p95 + " ms (target: under " + TARGET_P95_MILLIS + " ms)");
System.out.println(p95 < TARGET_P95_MILLIS ? "Requirement MET" : "Requirement NOT met");
}
}
p50 = 175 ms
p95 = 610 ms (target: under 300 ms)
Requirement NOT met
Only two requests out of 20 were slow (610 ms and 640 ms), but that is 10% of users, so the p95 target is missed. The average here is about 223 ms, which looks fine and would hide the problem. This is why NFRs use percentiles instead of averages.
Non-Functional Requirements in Configuration
Many NFRs are implemented in configuration rather than business logic. In Spring Boot, for example:
server:
compression:
enabled: true # performance: smaller responses
ssl:
enabled: true # security: HTTPS only
spring:
threads:
virtual:
enabled: true # scalability: handle many concurrent I/O requests
resilience4j:
timelimiter:
instances:
payment:
timeout-duration: 2s # reliability: never wait forever on the payment provider
management:
endpoints:
web:
exposure:
include: health, prometheus # observability: health checks and metrics
9. Gathering and Prioritising Requirements
- Talk to stakeholders: customers, product owners, support teams and operations all have different needs.
- Write user stories and use cases for functional requirements.
- Ask "how much?" and "how fast?" to turn vague wishes into measurable NFRs.
- Prioritise with MoSCoW: Must have, Should have, Could have, Won't have (this time).
- Record trade-offs: some NFRs conflict, such as strong security and maximum convenience, so agree on which wins.
- Revisit regularly: requirements change as the product and its users grow.
10. Using Requirements in System Design Interviews
The first few minutes of any system design interview should be spent on requirements. A good structure:
- List 3–5 core functional requirements and agree on what is out of scope.
- Ask about scale: number of users, requests per second and data size.
- Agree on key NFRs: latency, availability, consistency and durability targets.
- Use the NFRs to justify every design choice later, for example "we add a cache because search must be under 300 ms".
See System Design Process and Methodologies for the full process.
11. Common Mistakes
- Ignoring NFRs until the end: performance and security problems are expensive to fix after launch.
- Vague targets such as "fast" or "secure" that nobody can test.
- Using averages instead of percentiles, which hides slow requests.
- Asking for everything at the maximum, such as five nines of availability for an internal tool.
- Mixing design decisions into requirements, for example "use Redis" instead of "return results in 100 ms".
- Not testing NFRs with load, stress and security tests before release.
12. Summary
Functional requirements define what a system does: its features and business rules. Non-functional requirements define how well it does them: performance, scalability, availability, security, usability and more. Functional requirements are tested with pass or fail tests; NFRs are measured with numbers such as percentiles, uptime and throughput. Clear, measurable requirements of both kinds are the foundation of good system design, and NFRs in particular drive most of the architecture. Understanding both is key to building a system that not only works but also performs efficiently, securely and reliably.
Frequently Asked Questions (FAQ)
Q1. What is the difference between functional and non-functional requirements?
Functional requirements describe what a system should do, such as features and actions. Non-functional requirements describe how well it should do them, such as speed, security, availability and usability.
Q2. Can you give an example of a functional requirement?
"The system should allow users to register with their email and password." It describes a specific feature that either works or does not.
Q3. Can you give an example of a non-functional requirement?
"The dashboard should load in under 3 seconds for 95% of users." It describes a measurable quality of the system, not a feature.
Q4. Why are non-functional requirements important?
They make sure the system is fast, reliable, secure and easy to use. A system with every feature can still fail if it is slow, keeps crashing or leaks data.
Q5. How do you measure non-functional requirements?
With metrics such as response time percentiles (p95, p99), uptime percentage, throughput (requests per second), error rate, recovery time and security test results.
Q6. What are other names for non-functional requirements?
They are also called quality attributes, quality requirements, system qualities, technical requirements or the "-ilities" (scalability, availability, reliability, maintainability).
Q7. Who defines functional and non-functional requirements?
Functional requirements usually come from business users and product owners. Non-functional requirements are defined together by the business, architects, engineers and operations teams, because they affect cost and technology.
Q8. Is security a functional or a non-functional requirement?
Usually non-functional, such as "all data must be encrypted". Some security needs are functional features, such as "users can enable two-factor authentication". The behaviour is functional; the level of protection is non-functional.
Q9. Is performance a functional requirement?
No. Performance describes how fast the system responds or how much it can handle, so it is a non-functional requirement.
Q10. What is a user story?
A short description of a functional requirement from the user's point of view: "As a [type of user], I want [goal] so that [benefit]." For example: "As a customer, I want to save my address so that checkout is faster."
Q11. What makes a requirement testable?
It states a clear, measurable condition. "The system should be fast" is not testable; "the search API responds in under 300 ms for 95% of requests at 1,000 requests per second" is.
Q12. Why use percentiles instead of averages for performance requirements?
Averages hide slow requests. If 19 requests take 100 ms and one takes 5 seconds, the average looks fine but one user had a terrible experience. A p95 or p99 target makes sure most users get good performance.
Q13. How do non-functional requirements affect architecture?
They drive most big design choices. High availability leads to redundancy and failover, low latency leads to caching and CDNs, high scale leads to horizontal scaling and queues, and strict security leads to encryption and access control.
Q14. Can non-functional requirements conflict with each other?
Yes. Stronger security may reduce convenience, strong consistency may reduce availability, and very high performance may increase cost. Teams must agree on priorities and document the trade-offs.
Q15. What is the MoSCoW method?
A way to prioritise requirements into four groups:
- Must have: essential for the release.
- Should have: important but not critical.
- Could have: nice to have if time allows.
- Won't have: agreed to be out of scope for now.
Q16. How are functional requirements tested?
With unit, integration, system and user acceptance tests that check each feature behaves correctly. Each test passes or fails:
assertEquals(new BigDecimal("19.00"), service.placeOrder(lines));
Q17. How are non-functional requirements tested?
With specialised tests: load and stress tests (JMeter, Gatling, k6) for performance and scalability, security scans and penetration tests, chaos tests for resilience, and usability tests with real users. In production, monitoring checks that targets are still met.
Q18. What is the difference between an NFR and an SLA?
An NFR is an internal target the system is designed to meet, such as 99.95% availability. An SLA (Service Level Agreement) is a formal promise to customers, often with penalties, and is usually set a little lower than the internal target to leave a safety margin.
Q19. How should I handle requirements in a system design interview?
Spend the first few minutes clarifying them: list the core features, confirm what is out of scope, ask about scale, and agree on latency, availability and consistency targets. Then use those targets to justify each design decision.
Q20. What happens if non-functional requirements are ignored?
The system may work in testing but fail in real use: it slows down under load, goes offline, loses data or is breached. Fixing these problems after launch is usually much harder and more expensive than designing for them from the start.