Skip to main content

Non-Functional Requirements

What Your Agent Inherits

Your AI agent inherits a production system, not a prototype. Before the agent writes its first line of business logic, the FastAPI Chassis has already addressed non-functional requirements across security, reliability, performance, maintainability, and deployment. This chapter maps each of those requirements to the chapter that covers it.

Non-functional requirements are the quality attributes that determine whether software survives real traffic, real users, and real failures. They are invisible when they work and catastrophic when they don’t. An AI agent generating endpoints will produce functional code, routes that accept requests and return responses. What it won’t produce consistently is the infrastructure that makes those endpoints production worthy: the middleware ordering, the authentication validation, the structured logging, the container hardening, the health check separation.

This guide exists because those decisions should be made once, made well, and inherited by every piece of code that follows.

What Are Non-Functional Requirements?

Functional requirements describe what a system does. A login endpoint authenticates users. A search endpoint returns results. An upload endpoint stores files. These are the features, the things you can point to in a demo.

Non-functional requirements describe how well the system does it. How fast does the login respond under load? What happens when the database connection drops mid-request? Can you trace a single request across three services? Will the container restart correctly after an OOM kill? Can a new developer add an endpoint without understanding the middleware stack?

The software engineering literature calls these the “-ilities”: reliability, availability, maintainability, scalability, testability, observability. The ISO 25010 standard formalizes them into a product quality model with nine characteristics and dozens of sub-characteristics. In practice, most teams discover them the hard way: in production, at 2 AM, when something that worked in development fails under real conditions.

ISO/IEC 25010 — Software Product Quality model: 9 characteristics and their sub-characteristics

Here is the core problem with AI-generated code: non-functional requirements are exactly where LLMs are least reliable. Ask an LLM to implement a login endpoint and you’ll get a reasonable implementation every time. Ask it to configure middleware ordering, health check separation, and security headers, and you’ll get a different answer on each run. Functional requirements have clear right answers that appear in training data. Non-functional requirements involve tradeoffs, context, and operational experience that LLMs can approximate but never truly internalize.

The FastAPI Chassis solves this by removing non-functional requirements from the agent’s scope entirely. The chassis handles most of them. The agent handles business logic.

The NFR Matrix

The non-functional requirements addressed by the chassis group into six categories. Each requirement links to the chapter (or chapters) that implement it.

Security and Compliance

These requirements protect the system, its data, and its users from unauthorized access, data breaches, and regulatory violations.

Security. Defense against unauthorized access, injection, and data exposure. The chassis implements this across five layers: JWT authentication with three validation modes (Authentication), ASGI middleware with request filtering (Middleware), HTTP security headers against XSS and clickjacking (Security Headers), rate limiting against abuse (Rate Limiting), and hardened container images running as non-root (Docker).

Compliance. Adherence to security standards and organizational policies. The authentication system supports JWKS endpoint discovery for integration with enterprise identity providers (Authentication). Security headers enforce transport security (HSTS) and content policies (CSP) that compliance audits require (Security Headers).

Regulations. Meeting external legal and industry requirements. HSTS enforcement, CSP headers, and referrer policy configuration address requirements from frameworks like PCI-DSS and SOC 2 (Security Headers). Structured logging with immutable request traces provides the audit trail that regulators expect (Observability).

Auditability. The ability to trace and verify system behavior after the fact. Every request generates a unique trace ID that propagates across service boundaries via OpenTelemetry (Observability). Structured JSON logs capture request metadata, response codes, and timing automatically. The test suite verifies that audit relevant behaviors are covered (Testing).

Reliability and Operations

These requirements ensure the system remains functional, recoverable, and visible under failure conditions.

Fault Tolerance. Continued operation when components fail. Health check separation ensures Kubernetes does not restart pods during transient failures (Health Checks). The middleware stack processes requests through isolated layers so a failure in one concern does not cascade (Middleware).

Reliability. Consistent correct behavior over time. The test suite with high coverage ensures that regressions are caught before deployment (Testing). Health checks verify database connectivity and service health continuously (Health Checks). The async database layer handles connection pool exhaustion gracefully (Database).

Availability. System accessible when users need it. Readiness probes prevent traffic from reaching pods that cannot serve requests. Liveness probes restart pods that are genuinely stuck (Health Checks). Rate limiting prevents abuse from consuming all available capacity (Rate Limiting). Kubernetes deployment with rolling updates ensures zero-downtime releases (Deployment).

Recoverability. Ability to restore normal operation after failure. Alembic database migrations provide forward and rollback paths (Database). Health checks enable Kubernetes to automatically recover failed pods (Health Checks). Helm rollback capabilities restore previous deployment states (Deployment).

Observability. Visibility into system behavior at runtime. The three-pillar approach covers distributed tracing (OpenTelemetry), metrics (Prometheus), and structured logging (JSON) (Observability).

Debuggability. Ability to diagnose issues quickly. Trace IDs correlate logs across services. Structured logging provides queryable fields rather than unstructured text. Prometheus metrics expose latency percentiles and error rates (Observability). The test infrastructure reproduces issues in isolation (Testing).

Development and Maintenance

These requirements determine how efficiently the codebase can be understood, modified, tested, and evolved.

Maintainability. Ease of understanding and modifying the codebase. The builder pattern makes application assembly explicit and readable, where each concern is a named method call (Builder Pattern). The test suite serves as executable documentation (Testing).

Testability. Ease of verifying correct behavior. The factory function creates isolated application instances per test. Shared fixtures, factories, and async test patterns enable comprehensive coverage without boilerplate (Testing). The builder pattern’s explicit composition makes each concern independently testable (Builder Pattern).

Extensibility. Ease of adding new capabilities. The builder pattern means adding a new concern is a single setup_*() method call (Builder Pattern). The caching layer demonstrates the dependency injection pattern for optional capabilities (Caching).

Upgradability. Ease of updating dependencies and platforms. Digest-pinned Docker base images make updates explicit and reproducible (Docker). Alembic migrations version the database schema alongside code (Database). Helm chart versioning tracks deployment configuration changes (Deployment).

Serviceability. Ease of diagnosing and resolving production issues. Observability tooling identifies issues before users report them (Observability). Health checks provide automated status verification (Health Checks).

Manageability. Ease of operating and configuring the system. Helm values files parameterize deployment configuration without code changes (Deployment). The builder pattern centralizes application configuration in one place (Builder Pattern).

Performance and Scale

These requirements govern how the system behaves under load and how efficiently it uses resources.

Scalability. Ability to handle increasing load. Redis-backed rate limiting and caching work across multiple instances (Rate Limiting, Caching). The async database layer supports connection pooling for concurrent requests (Database). Kubernetes Deployment configuration enables horizontal pod autoscaling (Deployment).

Responsiveness. Speed of individual request handling. The middleware stack adds minimal overhead per request (Middleware). Caching avoids redundant computation for repeated requests (Caching). Rate limiting protects response times by shedding excess load (Rate Limiting).

Timeliness. Meeting time-based processing requirements. Request timing middleware measures and logs response latency (Middleware). Prometheus histograms track latency percentiles for SLA monitoring (Observability).

Affordability. Cost-effective resource usage. Caching reduces compute and database load for repeated operations (Caching). Multi-stage Docker builds produce minimal images that consume less memory and storage (Docker). Right-sized Kubernetes resource requests prevent over-provisioning (Deployment).

Deployment and Delivery

These requirements address how the system moves from code to running in production.

Deployability. Ease and safety of releasing new versions. Multi-stage Docker builds produce consistent, reproducible images (Docker). Helm charts with rolling update strategies enable zero-downtime deployments. VM deployment via Docker Compose provides an alternative for non-Kubernetes environments (Deployment).

Usability. Developer experience when working with the system. The builder pattern provides a readable, self-documenting application assembly (Builder Pattern). Auto-generated OpenAPI documentation gives API consumers interactive docs without additional work. The factory function pattern means create_app() is the single entry point. There is one way to create the application, and it is the right way.

AI and ML

This category addresses requirements specific to using AI agents as the primary development interface.

Deterministic Infrastructure for Non-Deterministic Agents. AI agents produce different code on every run. The functional requirements (endpoints, models, business logic) will be close enough each time. The non-functional requirements (middleware ordering, security configuration, container hardening) will vary unpredictably. The chassis turns this asymmetry into a feature rather than a risk: non-functional requirements are locked in as immutable infrastructure, and the agent operates exclusively in the business logic layer where variation is acceptable. Every chapter in this guide describes infrastructure the agent inherits but never generates.

NFR Quick Reference

NFRCategoryPrimary Chapters
SecuritySecurity & ComplianceAuthentication, Middleware, Security Headers, Rate Limiting, Docker
ComplianceSecurity & ComplianceAuthentication, Security Headers
RegulationsSecurity & ComplianceSecurity Headers, Observability
AuditabilitySecurity & ComplianceObservability, Testing
Fault ToleranceReliability & OperationsHealth Checks, Middleware
ReliabilityReliability & OperationsTesting, Health Checks, Database
AvailabilityReliability & OperationsHealth Checks, Rate Limiting, Deployment
RecoverabilityReliability & OperationsDatabase, Health Checks, Deployment
ObservabilityReliability & OperationsObservability
DebuggabilityReliability & OperationsObservability, Testing
MaintainabilityDevelopment & MaintenanceBuilder Pattern, Testing
TestabilityDevelopment & MaintenanceTesting, Builder Pattern
ExtensibilityDevelopment & MaintenanceBuilder Pattern, Caching
UpgradabilityDevelopment & MaintenanceDocker, Database, Deployment
ServiceabilityDevelopment & MaintenanceObservability, Health Checks
ManageabilityDevelopment & MaintenanceDeployment, Builder Pattern
ScalabilityPerformance & ScaleRate Limiting, Caching, Database, Deployment
ResponsivenessPerformance & ScaleMiddleware, Caching, Rate Limiting
TimelinessPerformance & ScaleMiddleware, Observability
AffordabilityPerformance & ScaleCaching, Docker, Deployment
DeployabilityDeployment & DeliveryDocker, Deployment
UsabilityDeployment & DeliveryBuilder Pattern
Deterministic InfrastructureAI/MLAll Chapters

Best Practices

  • Always define NFRs before writing the first line of business logic. Retrofitting security, observability, and reliability into an existing codebase is exponentially harder than inheriting them from a chassis.
  • Never let AI agents generate infrastructure code on each run. Non-functional requirements involve tradeoffs and operational experience that LLMs cannot reliably reproduce. Lock them into a chassis and let the agent focus on business logic.
  • Prefer the ISO 25010 quality model as your NFR checklist. Its nine characteristics and sub-characteristics provide comprehensive coverage that ad-hoc lists miss.
  • Always map each NFR to a specific implementation. An NFR without a chapter reference, code module, or configuration knob is an aspiration, not a requirement.

Further Reading


What the Agent Never Implements

The table above is a contract. Every row is a production requirement that your AI agent does not need to think about, configure, or generate. The chassis handles it. The guide documents it. The agent writes business logic.

This is the fundamental shift from template-based to chassis-based development. A template gives you starting code to modify. A chassis gives you 23 answered questions and a clear boundary: everything above the line is infrastructure, everything below is your feature.

Start with any chapter that addresses your most immediate concern. If you want to understand how the application is assembled, begin with Builder Pattern. If you want to understand how the application is observed in production, start with Observability. If you want to deploy immediately, jump to Docker and Deployment.

The order does not matter. The coverage does.