# NFR Encoding for AI Specs Non-functional requirements (NFRs) are the hardest spec dimension for AI code generation. AI agents naturally optimize for functional correctness; NFRs are often the last thing they consider. This guide covers how to encode NFRs in machine-readable formats so AI agents treat them as first-class constraints. ## The Problem AI agents, given a behavioral spec, will produce working code that: - Works correctly for 1 user but fails at 1000 - Handles the happy path but logs nothing - Is functionally correct but has a SQL injection vulnerability - Uses the correct algorithm but is 100x slower than required These are NFR failures. The agent didn't know the constraints because they weren't specified in a machine-actionable way. ## General Pattern Every NFR must include three things: 1. **Dimension** — what is being measured (latency, availability, concurrency, etc.) 2. **Threshold** — the specific, measurable boundary 3. **Verification method** — how compliance is checked | Dimension | Threshold Format | Example | |-----------|-----------------|---------| | Latency | `X units at Y percentile under Z load` | `200ms at P95 under 1000 concurrent users` | | Throughput | `X operations per Y time unit` | `5000 requests/second sustained` | | Availability | `X% over Y time period` | `99.9% uptime measured monthly` | | Concurrency | `X simultaneous users/connections` | `5000 simultaneous WebSocket connections` | | Storage | `X units per Y` | `1TB data, 30-day retention` | | Recovery | `X time to recover from Y failure` | `<5 min RTO for AZ failure` | | Accuracy | `X% correct under Y conditions` | `99.5% classification accuracy on test set` | ## Encoding NFRs in SPEC.md Within the SPEC.md template, NFRs are specified as a table: ```markdown ## Non-Functional Requirements | ID | Requirement | Threshold | Verification Method | |----|-------------|-----------|-------------------| | NFR-001 | API response time | <200ms at P95 under 1000 concurrent requests | k6 load test with p95 assertion | | NFR-002 | Uptime | 99.9% availability | Prometheus alerting + SLO tracking | | NFR-003 | Auth security | OWASP ASVS Level 2 | Semgrep SAST + dependency audit | | NFR-004 | Write audit log | All writes to user data produce audit event | Audit log must exist and be immutable | | NFR-005 | Max memory per request | <256MB heap | Memory profiling in staging | ``` The key insight: **each NFR must produce a PASS/FAIL verdict**, just like behavioral ACs. If you can't write a test for it, it's not an NFR — it's a hope. ## NFR by Category ### Performance | Dimension | How to Specify | Common Pitfall | |-----------|---------------|----------------| | Latency | Xms at Y percentile | Forgetting load conditions — "fast" is meaningless without concurrency | | Throughput | X operations/period | Mixing peak vs sustained — specify both | | Resource usage | X CPU, X memory, X storage | Not specifying units or measurement method | **Example:** "The search endpoint must respond within 500ms at P99 under 2000 req/s sustained load, measured by k6 on the staging environment. The API gateway must queue or reject requests exceeding this threshold, not crash." ### Security Security NFRs are unique: specifying them in the spec is itself a security best practice (shift-left security). | Concern | How to Specify | |---------|---------------| | Authentication | AuthN method (OAuth2, SAML, API keys), token format, expiry, scopes | | Authorization | AuthZ model (RBAC, ABAC), permission model, admin boundaries | | Input validation | Validation rules per field, injection prevention | | Secrets | Encryption at rest, in transit; secrets management approach | **Example:** "All API endpoints must validate JWTs from the OAuth2 provider before processing. Scopes are checked per RBAC matrix in docs/rbac.md. Input validation uses a whitelist approach — reject known-bad patterns at the API gateway level." ### Observability | Concern | How to Specify | |---------|---------------| | Logging | What events produce logs, log format (structured JSON), retention | | Metrics | What metrics are exposed (RED metrics for services: Rate, Errors, Duration) | | Tracing | Distributed tracing headers, span context propagation | **Example:** "Every API request produces a structured JSON log entry with: timestamp, request_id, method, path, status_code, duration_ms, user_id. The /metrics endpoint exposes Prometheus-formatted counters for request count, error count, and P50/P95/P99 latency." ### Reliability | Concern | How to Specify | |---------|---------------| | Fault tolerance | What failures the system survives without data loss | | Retry strategy | Backoff algorithm, max retries, circuit breaker thresholds | | Graceful degradation | What features degrade and how | **Example:** "The checkout service must survive any single downstream dependency failure without losing orders. Payments may queue for retry, but user session and cart data must persist. Circuit breakers open after 5 failures in 30 seconds." ## Encoding NFRs for Autonomous Agents For fully autonomous AI agents, NFRs need additional structure: ```markdown ### NFR Constraints for Implementation Agent The following constraints MUST be reflected in code architecture and dependencies, not just tested after implementation: 1. **Database:** Use PostgreSQL 16. Read replicas for reporting queries. Connection pooling via PgBouncer. 2. **Caching:** Redis for session cache (TTL: 30 min). No caching of user financial data. 3. **Async:** Background jobs via RabbitMQ. No long-running processes in request handlers. 4. **Observability:** OpenTelemetry instrumentation in every service. Export traces to Tempo. Implementation choices that violate these constraints without explicit spec amendment will be rejected at Gate 3. ``` This gives the agent architectural guardrails before it makes technology choices that are expensive to undo.