# API Performance Rules # ===================== api_rules: - id: "PERF-026" name: "Pagination required for list endpoints" severity: error description: | All list endpoints must support pagination. Unbounded lists cause performance issues: - Memory exhaustion - Slow response times - Database locks file_pattern: "**/api/**/*.py" anti_patterns: - '@router\\.get\\([^)]*\\)\\s*\\n(?:(?!limit|skip|offset|page).)*def\\s+\\w+.*:\\s*\\n(?:(?!limit|skip|offset|page).)*return.*\\.all\\(\\)' required_patterns: - "limit|skip|offset|page" example_bad: | @router.get("/products") def list_products(db: Session): return db.query(Product).all() example_good: | @router.get("/products") def list_products( skip: int = 0, limit: int = Query(default=20, le=100), db: Session = Depends(get_db) ): return db.query(Product).offset(skip).limit(limit).all() - id: "PERF-027" name: "Reasonable default page sizes" severity: warning description: | Default page sizes should be reasonable: - Default: 20-50 items - Maximum: 100-200 items Very large page sizes negate pagination benefits. file_pattern: "**/api/**/*.py" anti_patterns: - 'limit.*=.*Query\\([^)]*default\\s*=\\s*[5-9]\\d{2,}' - 'limit.*=.*Query\\([^)]*le\\s*=\\s*[1-9]\\d{3,}' example_bad: | limit: int = Query(default=500, le=10000) example_good: | limit: int = Query(default=20, ge=1, le=100) - id: "PERF-028" name: "Response compression" severity: info description: | Enable response compression for large responses: - GZip or Brotli - Significant bandwidth savings - Faster load times file_pattern: "**/main.py|**/app.py" suggested_patterns: - "GZipMiddleware|BrotliMiddleware|compress" - id: "PERF-029" name: "Efficient serialization" severity: info description: | Use Pydantic's response_model for efficient serialization. Avoid manual dict conversion. file_pattern: "**/api/**/*.py" anti_patterns: - 'return\\s+\\{[^}]*for\\s+\\w+\\s+in' - 'return\\s+\\[\\{.*for.*in.*\\]' suggested_patterns: - "response_model" - id: "PERF-030" name: "Avoid redundant queries in response" severity: warning description: | Don't trigger lazy-loaded relationships during serialization. Use eager loading or carefully control serialization. file_pattern: "**/api/**/*.py" - id: "PERF-031" name: "Streaming for large responses" severity: info description: | Use streaming responses for large data: - File downloads - Large exports (CSV, JSON) - Real-time data feeds file_pattern: "**/api/**/*.py" suggested_patterns: - "StreamingResponse|yield|generator" - id: "PERF-032" name: "Conditional requests support" severity: info description: | Support conditional requests to reduce bandwidth: - ETag validation - If-None-Match handling - 304 Not Modified responses file_pattern: "**/api/**/*.py" suggested_patterns: - "ETag|If-None-Match|304" - id: "PERF-033" name: "Field selection support" severity: info description: | Allow clients to request only needed fields. Reduces response size and serialization cost. file_pattern: "**/api/**/*.py" suggested_patterns: - "fields|include|exclude|sparse" - id: "PERF-034" name: "Avoid deep nesting in responses" severity: info description: | Deeply nested responses are slow to serialize. Consider flattening or using links instead. file_pattern: "**/api/**/*.py" - id: "PERF-035" name: "Endpoint response time monitoring" severity: info description: | Monitor API response times: - Set SLA targets - Alert on degradation - Track percentiles (p50, p95, p99) file_pattern: "**/main.py|**/middleware*.py" suggested_patterns: - "prometheus|metrics|timing|latency"