# Performance Budgets

Targets enforced in CI. Match the SLOs in [`runbooks/slo.md`](runbooks/slo.md).

## Frontend

| Metric                        | Budget                   | Tooling                                                |
| ----------------------------- | ------------------------ | ------------------------------------------------------ |
| Initial JS bundle (Angular)   | ≤ 250 KB gzipped         | `angular.json#budgets` (Phase 3 set) + bundle-analyzer |
| Initial JS bundle (Next.js)   | ≤ 250 KB gzipped         | `next build` output + bundle-analyzer                  |
| Largest Contentful Paint (3G) | ≤ 2.5 s                  | Lighthouse CI                                          |
| Cumulative Layout Shift       | ≤ 0.1                    | Lighthouse CI                                          |
| Time to Interactive (3G)      | ≤ 5 s                    | Lighthouse CI                                          |
| Per-component style (Angular) | ≤ 4 KB warn / 8 KB error | `angular.json#budgets`                                 |

## Backend

| Metric                       | Budget   | Tooling                                                  |
| ---------------------------- | -------- | -------------------------------------------------------- |
| API p95 latency              | ≤ 300 ms | Prometheus `http_server_request_duration_seconds_bucket` |
| API p99 latency              | ≤ 800 ms | Same source                                              |
| DB query p95                 | ≤ 50 ms  | `pg_stat_statements` + EXPLAIN                           |
| Queue processing p95 (audit) | ≤ 5 s    | BullMQ exporter                                          |

## Memory + footprint (per pod)

| Service       | Request       | Limit          |
| ------------- | ------------- | -------------- |
| `api-dotnet`  | 256 Mi / 200m | 768 Mi / 1000m |
| `api-nest`    | 192 Mi / 100m | 512 Mi / 500m  |
| `worker-nest` | 192 Mi / 100m | 512 Mi / 500m  |
| `web-angular` | 64 Mi / 50m   | 128 Mi / 200m  |
| `web-next`    | 192 Mi / 100m | 512 Mi / 500m  |

If a service consistently exceeds 80% of its limit, **raise the limit** rather than hope OOMs go away.

## CI gates

- Lighthouse CI fails the build when LCP > 2.5 s OR CLS > 0.1 OR JS > 250 KB on a representative route.
- Bundle analyzer report uploaded as an artifact for inspection.
- k6 baseline (`tools/load/baseline.js`) asserts `http_req_duration{name:dashboard} p(95) < 300`.

## When a budget breaks

1. Don't disable the budget. Fix the regression OR get an ADR-approved exception with an expiry.
2. Investigate before optimizing: capture numbers, identify the worst offender.
3. Use the `performance-budgeting` skill + `performance-agent`.

## Reviewed

Every 6 months — budgets that are always met can tighten; ones that are constantly broken get an ADR.
