polycratia

A fast database and a slow API do not contradict each other. The units just do not match.

Your database dashboard reports latency per statement. Your users feel latency per request. Nothing reconciles those two numbers for you, and the gap between them is where the time actually goes.

A request that fires two hundred queries at 2ms each gives you a green database and a 400ms endpoint. No single operation is slow. Everything is sequential.

The same arithmetic repeats at every other boundary in the request path. Serializing a deep object graph. A fan-out to carrier rate APIs, where your latency is the worst case of the slowest carrier rather than the average across all of them. A cache that is instant on a hit and a full recompute on a miss, so your median and your tail end up describing two different systems.

So I start with the count rather than with query time: how many round trips does one request make, to the database and to anything else reached over a socket? Request latency is dominated by the number of boundaries crossed, not by the cost of crossing one.

Which means the fix is usually shape work rather than tuning. Hydrate in sets instead of per row. Collapse read paths that were convenient to write and expensive to walk. Move fan-out off the response path and let the client ask for the result when it exists. Index work helps, but it only makes a cheap crossing cheaper.

This is also why "the database is fine" is such a common conclusion, and such an expensive one. It is true, and it closes the investigation one layer above the problem.

I write up more of these production latency patterns on my blog, if you want the longer version: https://polycratia.com/c/f8e6a3ba

The last time you chased a slow endpoint, what showed you the real cost was probably request-level tracing, or you sat there counting the queries by hand...

react

$ new-project --brief

or email hey@polycratia.com