SYSTEM-DESIGN Contents

Functional vs Non-Functional Requirements

Functional requirements describe what the system does; non-functional requirements define how well it must do it (SLOs, security, cost).

On this page

Why Requirements Decide Architecture

Most architecture mistakes happen before the first diagram: teams build a system optimized for assumptions they never wrote down. Production-first design starts by separating what the system must do (functional requirements) from the qualities it must meet under load and failure (non-functional requirements).

Functional Requirements

Functional requirements describe user-visible capabilities and workflows. They answer: “What does this system do?” They are often expressed as endpoints, screens, business actions, and core entities.

  • Create and authenticate users
  • Upload files and download them later
  • Search content and paginate results
  • Send notifications for specific events

Non-Functional Requirements

Non-functional requirements define how well the system must perform and what constraints it must satisfy. They answer: “How reliable, fast, safe, and cheap must this be?” These requirements dominate production outcomes.

  • Reliability: uptime targets, error budgets, graceful degradation
  • Performance: latency targets (p95/p99), throughput, tail behavior
  • Scalability: peak load, growth rate, traffic spikes
  • Consistency: strong vs eventual correctness per workflow
  • Security: auth, data protection, auditability, abuse resistance
  • Cost: compute, storage, egress, operational overhead
  • Operability: monitoring, incident response, deploy/rollback

Non-Functional Requirements Are Often Hidden

Teams frequently write a feature list but ignore constraints like p99 latency, provider outages, or abuse traffic. Then the system “works” in staging but fails in production. If you do not specify non-functional requirements, you are implicitly accepting the default: unknown reliability and unpredictable cost.

From Requirements to Concrete Decisions

Requirements should drive specific engineering choices, not generic best practices. The same feature can demand different architectures depending on constraints.

  • If you need p99 < 200ms, you will likely need caching, strict timeouts, and queue control.
  • If you need 99.9% availability, you need redundancy, fast failover, and safe degradation paths.
  • If you need strong correctness for payments, you need transactions and idempotency.
  • If you expect traffic spikes, you need rate limiting, backpressure, and load shedding.

A Practical Requirements Sheet

Write requirements in a form that forces clarity. Avoid vague goals like “fast” or “scalable.” Use measurable targets and realistic scenarios.

Functional
- Users can create accounts and log in
- Users can upload files and share a link
- Admins can delete content

Non-functional
- Availability: 99.9% monthly
- Latency: p95 < 200ms for read APIs, p95 < 500ms for writes
- Peak load: 2,000 RPS sustained, 10,000 RPS bursts for 60s
- Data growth: 50GB/month uploads, retain 1 year
- Consistency: uploads must not duplicate; deletes must be immediate for the owner
- Security: protect against brute force, abuse, and token leakage
- Ops: on-call can debug using requestId; rollback within 10 minutes

Common Mistakes

  • Defining only functional requirements and hoping the system scales later
  • Setting SLOs without understanding dependency budgets
  • Ignoring failure modes (timeouts, retries, partial outages)
  • Choosing microservices without operational requirements that justify them

Production-First Takeaway

Functional requirements define what you build. Non-functional requirements define whether it survives production. Treat non-functional requirements as first-class inputs: they determine your architecture, your cost, and your incident rate.