When designing a system, both functional and non-functional requirements are important. They describe different aspects of the system behavior and have severe implications over how it is designed, implemented, maintained, and even deprecated.
In a nutshell:
Functional requirements define what the system should do and are often easy to explain in a flowchart algorithm or use case. For example: what should a certain button do when it’s pressed or when should the notification be shown with what content.
Non-Functional Requirements (NFR) define the system behavior in ways that are not easily described using a flowchart. For example: security, reliability, scalability, etc.
Most computer engineering curriculum is focused on the functional requirements: data structure, data processing, etc. Most junior/midlevel programmers I’ve worked with can handle functional requirements easier than non-functional requirements. NFRs usually require a degree of experience and holistic system thinking that’s not taught in school, or if it is, the technical innovations quickly deprecate that knowledge.
But make no mistake, functional requirements are more important than non-functional requirements. As the saying goes:
First make it work, then make it better.
NFRs really take their meaning in relation to the functional requirements. So, let’s take a quick look at them first.
Functional Requirements
Functional requirements define what the software system should do. These requirements are specific commands or functions the system must perform, tasks that the software must accomplish, the interactions it must support, the data it must gather or process.
Functional requirements are directly related to the primary activities and processes that the software will enable.
For example:
The website must have a shopping cart and the user should be able to check out any time during their visit.
Users must be able to log into their accounts using a username and password.
The system should generate reports within 30 seconds of receiving a request.
The backend must support the creation, deletion, and modification of user profiles.
Functional requirements are usually captured in use cases. Sometimes they are described in user stories to define the system behavior from the user's perspective.
Non-Functional Requirements
Non-functional requirements, on the other hand, describe how the system performs a certain function rather than what functions it performs. These are constraints or qualities that the software must have, such as reliability, performance, security, usability, maintainability, extensibility, testability, etc. Non-functional requirements do not affect the basic functionality of the system; rather, they ensure the usability and effectiveness of the entire system and can affect the user experience deeply.
For example:
The system should load the homepage in less than three seconds.
Data should be encrypted using AES encryption.
The software must be operational 99.9% of the time.
The app must use our branding colors and logo and be fully accessible to screen readers.
The system should use pseudonymization to comply with local data protection law
Non-functional requirements are generally harder to define, implement and measure, but they have huge implications on the system design, cost, and user satisfaction.
The way you design a system that handles 10 requests per minute is entirely different than a system that handles millions of requests per second.
There are a lot of good newsletters about system design at scale for example:
ByteByteGo by
Why are NFRs tricky?
It’s good to have that system design knowledge in your toolbox but what really makes NFRs tricky is that in practice you’re rarely given a set of NFRs to design a system. You’re supposed to come up with them asking the right questions, gathering the right data, and doing experimentation.
For example:
System Lifecycle: NFRs need to be considered early in the system design process, as they can significantly influence architecture and technology choices. Retrofitting a system to meet non-functional requirements after the fact can be costly and difficult, if not impossible.
Vagueness and Subjectivity: NFRs often involve qualitative criteria rather than quantitative ones. This makes them subjective and open to interpretation. For example, requirements like "the system should be user-friendly" or "the software must be responsive" are subjective and can mean different things to different stakeholders.
Measurement Challenges: Unlike functional requirements, which can be easily tested and validated (e.g., a function either works or it doesn't), non-functional requirements can be difficult to measure precisely. Determining how fast is fast enough or what level of security is adequate requires specific metrics that might not be straightforward to establish or agree upon. Sometimes a benchmark is used to measure the system in isolation. The problem is that the benchmarks can be quite subjective and differ from how the system is used in the while and in relation to other systems in an ever evolving and dynamic environment.
Estimation Challenges: Due to implications in system design, it’s tempting to overestimate its usage in the future and design something capable of handling 100x or even more load or usage. This is a clear case of tech gamble. Only time will tell if it was the right bet. What is considered adequate today in terms of usability, security, or performance might change rapidly due to technological advancements or changing user expectations. This evolution can make some NFRs moving targets that are hard to satisfy definitively.
Trade-offs: Addressing non-functional requirements often involves trade-offs with other system attributes. For example, increasing security might hurt usability, reduce system performance. Similarly, scalability often comes with an increased cost. The cost and budget aspect alone can have a significant influence on the system design. Balancing these trade-offs requires careful consideration and often complex decision-making and a dash of luck!
NFRs are hard because they require experience, negotiations, and trade-offs. It is harder to see their impact short term or sometimes never (e.g. security). And because of that NFRs don’t enjoy the same quick feedback loop as the functional requirements.
There’s a degree of guess work and budgeting involved in NFRs that make them particularly tricky to get right.
My monetization strategy is to give away most content for free. However, these posts take anywhere from a few hours to days to draft, edit, research, illustrate, and publish. I pull these hours from my private time, vacation days and weekends. Recently I went down in working hours and salary for 10% to be able to spend more time.
You can support me by sparing a few bucks for a paid subscription. As a bonus you get access to my WIP book Reliability Engineering Mindset. Right now, you can get 20% off via this link.