A short-video recommendation service was designed when a median session pulled 20 videos and feature computation took 40 ms. Two years later sessions pull 200 videos, the model is larger, and p99 recommendation latency has quietly tripled - yet no single change looks responsible. How do you diagnose this as a constraints problem rather than a code problem?
Show the full answer Hide the answer
The situation
Nothing broke. There is no bad deploy to roll back, no dependency outage, no decisive hot spot. The p99 simply drifted. Teams in this position usually profile, find nothing conclusive, and add capacity.
The diagnosis
Write down every constraint the original design was sized against, then measure each one today:
| Original constraint | Assumed | Actual now |
|---|---|---|
| Videos per session | 20 | 200 |
| Candidate pool per request | 10k | 100k |
| Feature vector size | small | several times larger |
| Cache hit rate on user features | high | degraded by longer sessions |
| Round trips to feature stores | 1 batch | several batches |
Each change was individually defensible and shipped with a green dashboard. The architecture was sized against a set of numbers that all moved in the same direction at once, and nobody was accountable for the product of those numbers.
What separates this from a code problem
A code problem has a location. This has none — the latency is spread across a path that got uniformly heavier. The fix is not in a profiler; it is a decision about which constraint to re-establish:
- Bound the candidate pool and recover quality with a better ranker rather than a bigger one.
- Move feature computation off the request path into a precomputed store, accepting staleness.
- Batch and pipeline the fan-out so per-request round trips stop scaling with session length.
Only after choosing does profiling become useful, because now you know what you are optimising.
The lesson
A constraint has a shelf life. Record the volume assumption next to the decision it justified, and put the assumption itself on a dashboard. The failure was not slow code — it was that no alarm existed for "the number this design assumed has moved by 10x".