51 lines
2.2 KiB
Markdown
51 lines
2.2 KiB
Markdown
# Backend Performance — Derived Rules
|
|
|
|
> Derives from `domains/performance/first-principles.md` P1 (Measure First), P3 (Complexity Awareness), P4 (Resource Bounds).
|
|
|
|
## Measure First (P1)
|
|
|
|
- p50, p95, p99 latencies. The average hides the long tail.
|
|
- Throughput (req/s) under load. Saturation point (where latency rises).
|
|
- Resource utilization: CPU, memory, I/O, network. Each is a budget.
|
|
|
|
## N+1 Queries (P3 Complexity Awareness)
|
|
|
|
- A query in a loop is an N+1. It is O(N) queries instead of O(1).
|
|
- Detect with a query counter in tests. A test that issues 100 queries is failing.
|
|
- Fix with a JOIN, a batch load, or a dataloader. Never "we'll fix it later."
|
|
|
|
## Caching (P5 Caching with Intent)
|
|
|
|
- Cache what is: expensive to compute, stable, read often.
|
|
- Invalidation is designed: TTL, event-based, or version-based. Never "we'll just clear it."
|
|
- A cache without an invalidation strategy is a cache that serves stale data forever.
|
|
- Multi-level: HTTP cache → CDN → app cache → DB. Each layer has its own rules.
|
|
|
|
## Async and Concurrency (P7 Async When Independent, see `domains/concurrency/`)
|
|
|
|
- I/O-bound work is async. Don't block a thread on a network call.
|
|
- CPU-bound work is in a worker, not the request path.
|
|
- Bounded queues everywhere (P9 Bounded Queues). Unbounded = OOM.
|
|
|
|
## Database (P4 Resource Bounds, see `domains/data/indexing.md`)
|
|
|
|
- Connection pool: bounded. The DB has a connection limit; the pool respects it.
|
|
- Slow queries: logged, explained, fixed. A 10-second query is a bug.
|
|
- Pagination on large tables: cursor, not offset. Offset scans rows.
|
|
|
|
## Resource Bounds (P4)
|
|
|
|
- Memory: bounded. A request that allocates unbounded memory is a DoS vector.
|
|
- Timeouts: every external call has one. A call without a timeout is a call that can hang forever (P8 Timeout Discipline).
|
|
- File handles, DB connections, HTTP connections: all bounded, all pooled.
|
|
|
|
## What Violates Backend Performance
|
|
|
|
| Violation | Principle |
|
|
|-----------|-----------|
|
|
| N+1 query in a loop | P3 |
|
|
| No timeout on an HTTP call | P4, P8 (concurrency) |
|
|
| Unbounded in-memory sort | P4 |
|
|
| Cache with no invalidation | P5 |
|
|
| `SELECT *` | P4 (data P10) |
|
|
| Connection pool size = 1000 | P4 (DB limit) | |