Non-Functional Requirements (NFR)
How interviewers grade scalability, security, performance, monitoring, availability, and reliability — and how to state targets with real numbers.
① What are NFRs — and how interviewers grade them
Functional requirements describe what the system does: "users can post tweets, follow others, see a timeline." Non-functional requirements (NFRs) describe how well it does it: latency, uptime, security, scale, durability. In interviews, NFRs separate mid-level ("we need a database") from senior ("p99 < 200 ms at 50K peak QPS with 99.95% availability").
Why it matters
Architecture follows NFRs, not features. A chat app and a batch payroll system both "store messages" but NFRs diverge wildly: chat needs <100 ms delivery and high availability; payroll needs ACID, audit logs, and correctness over raw speed. Interviewers dock candidates who jump to Kafka without stating latency or consistency targets.
Grading rubric (typical FAANG-style):
- Junior: lists NFR buzzwords without numbers.
- Mid: states 1–2 NFRs with rough numbers (QPS, latency).
- Senior: maps each NFR to components, trade-offs, and failure modes.
- Staff: prioritizes NFRs when they conflict ("we sacrifice eventual consistency on likes to hit p99 during peak").
Where to use
First 5 minutes of every system design interview — immediately after functional scope. Also in RFCs, SLO documents, and product requirement docs (PRDs). Production teams encode NFRs as SLOs/SLAs monitored 24/7.
Real use cases
- Stripe API SLA: 99.99% availability, idempotent POST with
Idempotency-Key, PCI-DSS for card data — NFRs drive API design. - Google Search: p95 latency ~200 ms historically; massive scale NFR drove caching, index sharding, and edge serving.
- Hospital EMR: availability + durability > raw speed; audit and encryption NFRs dominate architecture.
When NOT to use
Don't recite a 20-item NFR checklist for a 15-minute "design a rate limiter" question — pick 3–4 relevant NFRs (latency, accuracy, scale). Don't claim NFRs you won't design for ("five nines globally" without multi-region budget).
Alternatives
| Term | Meaning | Example |
|---|---|---|
| SLA | Contract with customer; breach = credits | 99.9% uptime per month |
| SLO | Internal target, tighter than SLA | p99 < 150 ms (SLA says 300 ms) |
| SLI | Metric you measure | Ratio of requests < 200 ms |
| NFR | Requirement category | Security, performance, scale |
| Quality attribute | Academic synonym for NFR | Modifiability, testability |
Execution / data flow
Product ask → List functional reqs → List NFRs with numbers → Prioritize conflicts → Map NFR → component → Validate in wrap-up
WHAT: post tweet
HOW FAST: p99 < 200 ms
HOW RELIABLE: 99.9%
HOW SAFE: OAuth + TLS
| NFR category | Interview question to ask | Example target |
|---|---|---|
| Scale | DAU? read/write ratio? | 10M DAU, 100:1 read/write |
| Performance | p99 latency budget? | Reads < 200 ms, writes < 500 ms |
| Availability | Downtime acceptable? | 99.9% = 43 min/month |
| Reliability | Data loss acceptable? | 0 lost payments; RPO 0 for money |
| Security | Auth, PII, compliance? | OAuth2, encrypt PII at rest |
| Consistency | Stale reads OK? | Strong for wallet; eventual for feed |
② Scalability as NFR — elasticity, 10× growth, horizontal targets
Scalability NFR answers: "Can the system grow 10× users without 10× cost or a rewrite?" It includes capacity (handle peak QPS), elasticity (auto-scale with traffic), and growth headroom (architecture supports next year's DAU).
Why it matters
Products that 10× overnight (viral app, Black Friday) die if NFR was "works on my laptop." Scalability NFR forces horizontal design early: stateless APIs, partitioned data, caches, queues. Interviewers want you to name what breaks first at 10× — usually DB writes or hot keys, not CPU on app servers.
Elasticity means scale down at 3 AM to save cost — NFR for cost-conscious SaaS, not just scale up.
Where to use
- User-facing APIs with unpredictable growth (social, gaming launches).
- Multi-tenant SaaS (noisy neighbor isolation NFR).
- Event spikes: ticket sales, elections, sports finals.
- Capacity planning: "support 50K peak QPS within 18 months."
Real use cases
- Twitter timeline read NFR: 300M DAU, ~175K avg QPS, peaks ~1–2M QPS during events → CDN + cache + read replicas mandatory; fan-out on write for celebrities.
- Startup NFR: "10× in 12 months" → avoid premature microservices but design stateless monolith + managed RDS + Redis from day one.
- AWS auto-scale NFR: scale app tier 10→200 instances in <5 min when CPU > 70% for 2 min; scale down with 15 min cooldown.
When NOT to use
- Internal admin tool with fixed 200 users — horizontal scale NFR wastes money; vertical RDS is fine.
- Claiming infinite scale without cost discussion — staff interviews ask $/month at target QPS.
- Sharding at launch for 100 QPS — violates pragmatic scalability (scale what hurts).
Alternatives
| Strategy | 10× lever | Time to implement | Cost curve |
|---|---|---|---|
| Optimize code/DB | 2–5× | Days–weeks | Low |
| Cache + CDN | 5–20× read relief | Weeks | Medium |
| Read replicas | 3–10× reads | Days | Medium |
| Horizontal app scale | Linear with instances | Hours (K8s) | Linear |
| Sharding / partition | 10×+ writes | Months | High ops |
| Serverless | Elastic per request | Days | Spiky-friendly |
Execution / data flow
10× growth math example: Today 1M DAU, 10M requests/day ≈ 116 QPS avg, peak 1.2K QPS. After 10×: 10M DAU ≈ 1.2K avg, 12K peak QPS. App: 12K/200 per instance ≈ 60 instances (+ buffer → 120). DB reads at 90% cache hit: 1.2K DB QPS vs 12K without cache.
Define today's QPS → multiply 10× → identify bottleneck (DB, cache, egress) → apply scale pattern → verify auto-scale policy → document next bottleneck
NFR input
calculated
auto-scale
90% hit
1.2K read/s
| Metric | Today | 10× target | Component |
|---|---|---|---|
| DAU | 1M | 10M | — |
| Peak QPS | 1.2K | 12K | LB + app tier |
| Storage | 10 TB | 100 TB | S3 + lifecycle |
| Cache RAM | 8 GB | 64 GB | Redis cluster |
| Monthly cost | $5K | $35–50K | estimate aloud |
③ Security NFR — auth, encryption, OWASP, zero trust
Security NFRs protect confidentiality, integrity, and availability from adversaries — not accidents. In interviews, cover authentication (who), authorization (what they can do), encryption (in transit and at rest), and compliance (PCI, HIPAA, GDPR) when relevant.
Why it matters
One SQL injection or leaked S3 bucket ends companies. Security NFRs shape: TLS everywhere, secrets not in code, least-privilege IAM, audit logs for 7 years. Senior candidates mention OWASP Top 10 briefly and map threats to controls — not "we'll be secure."
Zero trust: never assume internal network is safe — verify every service call (mTLS, JWT, service mesh policies).
Where to use
- Any user-facing API with accounts (OAuth2/OIDC, session management).
- Payment, health, government — regulatory NFRs mandatory.
- Multi-tenant SaaS — tenant isolation NFR (no cross-tenant data leak).
- Internal microservices — service-to-service auth, not IP allowlists only.
Real use cases
- Auth0 / Google Sign-In: OAuth2 NFR — don't store passwords; delegate to IdP; short-lived access tokens (15 min) + refresh tokens (rotating).
- PCI-DSS for cards: never store raw PAN in your DB — Stripe tokenization; scope reduction NFR.
- AWS S3 breach pattern: encryption at rest (SSE-S3/KMS) + bucket policy deny public — NFR "no public objects."
- OWASP A03 Injection: parameterized queries, ORM — NFR for every SQL-backed design.
When NOT to use
- Over-engineering mTLS for a public read-only blog — TLS to client is enough.
- Building custom crypto — NFR satisfied by AES-256-GCM and TLS 1.3 via libraries.
- 30-minute security deep dive in a system design unless role is security-focused.
Alternatives
| Control | Mechanism | When |
|---|---|---|
| AuthN | OAuth2, SAML, passkeys | User identity |
| AuthZ | RBAC, ABAC, OPA policies | Per-resource permissions |
| Transport | TLS 1.3, mTLS internal | All external + zero trust internal |
| At-rest encryption | AES-256, KMS per-tenant keys | PII, secrets, backups |
| WAF / rate limit | Cloudflare, API gateway | DDoS, brute force |
| Audit log | Immutable append-only store | Compliance, forensics |
Execution / data flow
Client TLS → API Gateway (JWT validate, rate limit) → Service (RBAC check) → DB (encrypted column for PII) → Audit log async
TLS 1.3
JWT + WAF
OAuth2
RBAC
KMS
| OWASP risk | Control in design | Interview one-liner |
|---|---|---|
| Broken access control | Check owner_id on every read | "Authorize in service layer, not UI" |
| Injection | Prepared statements | "No string concat SQL" |
| Sensitive data exposure | TLS + field-level encryption | "PII encrypted, keys in KMS" |
| SSRF | Allowlist outbound URLs | "Webhook fetcher uses proxy" |
| Security misconfiguration | IaC, deny public S3 | "Terraform + policy scans" |
④ Performance NFR — latency p99, throughput, tail latency
Performance NFRs define how fast and how much: latency (p50, p95, p99), throughput (QPS/RPS), and tail latency (worst 1% — what angry users hit). Throughput without latency is meaningless: 1M QPS at 5 s each is useless.
Why it matters
Users abandon after ~3 s page load; APIs targeting mobile need p99 < 300 ms. Tail latency dominates SLAs — average 50 ms with p99 2 s means 1% of users suffer. Performance NFR drives caching, connection pooling, async paths, and "don't N+1 query."
Little's Law: concurrency = QPS × latency — at 5K QPS and 100 ms latency you need ~500 in-flight requests capacity.
Where to use
- User-facing read APIs (search, feed, product page).
- Real-time systems (gaming, trading, video calls).
- Batch is different NFR — throughput jobs/hour, not p99 ms.
- Mobile clients on 3G — stricter payload size NFR (<50 KB JSON).
Real use cases
- Google search NFR: sub-second perceived; aggressive caching and index locality.
- Uber dispatch: p99 < 100 ms for matching nearby drivers — geo index + in-memory grids.
- Netflix startup: time-to-first-frame NFR drives CDN edge caches of manifest + first segment.
- API gateway SLA: p99 < 200 ms excluding client network; measure server-side spans only.
When NOT to use
- Same p99 target for writes and reads — writes often 2–5× looser (500 ms OK for create order).
- Optimizing microsecond latency for nightly ETL — wrong metric (use job duration).
- Ignoring payload size — 5 MB JSON blows mobile performance even at 50 ms server time.
Alternatives
| Technique | Latency impact | Trade-off |
|---|---|---|
| CDN edge | −100 to −200 ms RTT | Stale static content |
| Redis cache | −10 to −50 ms DB | Consistency |
| Connection pool | −20 ms conn setup | Pool sizing |
| Parallel fan-out | max(A,B) vs A+B | Complexity |
| Async non-critical | −50 to −500 ms user path | Delayed side effects |
| gRPC vs REST JSON | −5 to −20 ms serialize | Browser support |
Execution / data flow
Latency budget (p99 < 200 ms read):
Budget 200 ms → allocate: network 40 ms + LB 5 ms + app 50 ms + cache 2 ms + DB 15 ms + margin 78 ms → if DB spikes, shed load or cache more
p99 ~ 250 ms
p99 ~ 90 ms
| Metric | Typical target | Measurement |
|---|---|---|
| p50 latency | 50–80 ms API | Prometheus histogram |
| p99 latency | < 200 ms read | Exclude client RTT optional |
| Throughput | 12K peak QPS | Load test + prod metrics |
| Error budget | 0.1% slow requests | SLO burn alerts |
| Payload size | < 100 KB typical API | Compression gzip/br |
⑤ Monitoring NFR — metrics, logs, traces, alerting, SLOs
You cannot meet NFRs you cannot measure. Monitoring NFR defines what to observe (metrics, logs, traces), how fast to detect failure (<1 min alert), and SLO targets that drive alerting and error budgets.
Why it matters
Outages without observability mean hours of blind debugging. Google SRE practice: SLI → SLO → SLA. If p99 latency SLO is 200 ms and error budget burns 50% in a day, freeze feature launches and fix perf. Interview wrap-up without monitoring sounds incomplete.
Where to use
- Every production service — non-negotiable NFR.
- High availability designs — prove failover worked via synthetic checks.
- Capacity planning — QPS, CPU saturation, DB conn pool graphs.
- Security — audit logs, anomaly detection on auth failures.
Real use cases
- Datadog / Prometheus stack: RED metrics (Rate, Errors, Duration) per service; alert when p99 > 300 ms for 5 min.
- Distributed tracing (Jaeger): one slow request shows DB span 1.8 s — missing index found in minutes.
- Structured logs (JSON):
request_idcorrelates across 12 microservices. - PagerDuty on SLO burn: 99.9% monthly budget — alert at 25% consumed in 24 hr.
When NOT to use
- Logging every byte of PII — violates security NFR; log IDs not emails.
- Alert on everything — alert fatigue; page humans only on user-impacting SLO breach.
- 5-minute deep dive on tool names unless interviewer asks ops details.
Alternatives
| Pillar | Tool examples | Best for |
|---|---|---|
| Metrics | Prometheus, CloudWatch, Datadog | Aggregates, dashboards, alerts |
| Logs | ELK, Loki, Splunk | Debugging specific request |
| Traces | Jaeger, Tempo, X-Ray | Latency breakdown |
| Synthetic | Pingdom, canaries | Proactive uptime check |
| Profiling | pprof, continuous profiler | CPU hotspots in prod |
Execution / data flow
Request → App emits metrics (latency histogram) + trace spans → Log line with trace_id → Collector → Dashboard + alert rule → PagerDuty if SLO burn
metrics/logs/traces
collector
dashboards
SLO burn
| SLI | SLO example | Alert threshold |
|---|---|---|
| Availability | 99.9% successful requests | >0.1% 5xx for 5 min |
| Latency | 99% < 200 ms | p99 > 300 ms 10 min |
| Saturation | CPU < 70% avg | >85% 15 min → scale |
| DB connections | Pool < 80% | >90% → leak or scale |
| Queue lag | < 1 min consumer lag | >5 min → worker scale |
⑥ Availability NFR — uptime %, HA, failover, multi-region
Availability NFR is the fraction of time the system is usable: 99.9% (three nines) = ~43 minutes downtime/month; 99.99% (four nines) = ~4.3 minutes/month. Achieved via redundancy, failover, health checks, and multi-region — not wishful thinking.
Why it matters
Downtime costs money and trust — Amazon estimated $220K/minute at peak (historical anecdote). Availability NFR determines single-AZ vs multi-AZ vs multi-region. You cannot get four nines on a single server; interviewers check you know the math and architecture cost.
Where to use
- Payment, auth, core API — high availability NFR (99.9%+).
- Global products — multi-region for disaster recovery (region loss).
- Stateful systems — leader failover (Postgres Patroni, Redis Sentinel).
- Planned maintenance — rolling deploys without hard downtime NFR.
Real use cases
- AWS multi-AZ RDS: synchronous standby in second AZ; failover ~60–120 s; meets many 99.95% NFRs.
- Route 53 health checks: DNS failover to secondary region if primary health check fails 3×.
- Kubernetes: 3 replicas + PDB + rolling update — pod death invisible to users.
- Status page honesty: 99.9% SLA with credits if breached — contractual NFR.
When NOT to use
- Five nines (99.999%) for internal CI tool — ~26 sec/month downtime budget unrealistic for cost.
- Multi-region active-active for every app — 2× cost + consistency pain; reserve for tier-0 services.
- Claiming 100% availability — impossible; define degraded mode (read-only) instead.
Alternatives
| Pattern | Typical availability | Failover time | Cost |
|---|---|---|---|
| Single server | 95–99% | Hours (manual) | $ |
| Multi-instance + LB | 99.5–99.9% | Seconds (health check) | $$ |
| Multi-AZ DB | 99.9–99.95% | 1–2 min | $$$ |
| Multi-region active-passive | 99.95–99.99% | 5–30 min DNS | $$$$ |
| Multi-region active-active | 99.99%+ | Near zero | $$$$$ |
Execution / data flow
Health check fails → LB removes bad nodes → if AZ down → promote replica → if region down → DNS to secondary region → runbook + status page
100% traffic
async replica
| Uptime % | Downtime/month | Downtime/year | Architecture hint |
|---|---|---|---|
| 99% (two nines) | 7.2 hours | 3.65 days | Single region OK |
| 99.9% | 43 minutes | 8.7 hours | Multi-AZ, redundancy |
| 99.95% | 22 minutes | 4.4 hours | Auto failover DB |
| 99.99% | 4.3 minutes | 52 minutes | Multi-region, no single AZ |
| 99.999% | 26 seconds | 5.2 minutes | Active-active global |
⑦ Reliability NFR — durability, fault tolerance, retries, idempotency
Reliability is whether the system behaves correctly under failure: no lost data (durability), graceful degradation (fault tolerance), and correct behavior when messages duplicate (idempotency). Availability is "up"; reliability is "right when up (and after recovery)."
Why it matters
Double-charging a customer once destroys more trust than 5 min outage. Reliability NFRs drive: replicated storage (11 nines S3 durability), at-least-once delivery + idempotent consumers, circuit breakers, and RPO/RTO for backups. Kafka without idempotent writes loses money on retry storms.
RPO (Recovery Point Objective): max data loss window — 0 for payments. RTO (Recovery Time Objective): max time to restore — 15 min for tier-1 API.
Where to use
- Payment, inventory, booking — durability + idempotency mandatory.
- Message queues — at-least-once delivery assumed; design consumers idempotent.
- Microservices — circuit breakers when dependency fails; don't cascade.
- Backups — nightly snapshots + PITR for DB; test restore quarterly NFR.
Real use cases
- Stripe idempotency keys: same POST retried returns same result — reliability NFR for flaky mobile networks.
- S3 durability 99.999999999%: erasure coding across AZs — object store reliability NFR.
- Outbox pattern: DB transaction includes outbox row → worker publishes to Kafka — no lost events on crash between DB and queue.
- Circuit breaker (Hystrix/resilience4j): stop calling failing payment API after 50% errors — fail fast, protect reliability of core path.
When NOT to use
- Idempotency store for every read-only GET — unnecessary complexity.
- Sync replication globally for analytics logs — eventual OK; don't over-apply payment rules.
- Infinite retries without backoff — amplifies outages (retry storm).
Alternatives
| Pattern | Guarantee | Use when |
|---|---|---|
| At-most-once | May lose message | Metrics OK to drop |
| At-least-once + idempotent | No duplicate effect | Payments, orders |
| Exactly-once | Hard in distributed | Kafka transactions, Flink |
| Saga | Distributed compensating txs | Multi-service workflows |
| 2PC | Strong atomic commit | Rare; latency + blocking |
Execution / data flow
Client POST payment + Idempotency-Key → API upsert idempotency record → DB txn debit+credit → return 200 → on timeout client retries same key → API returns cached 200 (no double charge)
same key
check key
Redis/DB
ACID txn
1s wait
2s wait
4s wait
| Failure | Reliability control | Target |
|---|---|---|
| Duplicate request | Idempotency key | 0 duplicate charges |
| Worker crash mid-job | At-least-once + idempotent worker | Job eventually done once |
| DB primary dies | Replica promote + WAL | RPO < 1 min, RTO < 2 min |
| Dependency timeout | Circuit breaker + fallback | Degraded mode, not hang |
| Region loss | Cross-region backup | RPO 15 min, RTO 1 hr |
Retry numbers: max 3–5 retries, exponential backoff 1s→2s→4s, jitter ±20%; dead-letter queue after exhaustion; alert on DLQ depth > 100.