Your database can be fast and your API still slow. All a fast database proves is that one of the four things in your request path is cheap.
Query time gets measured per statement. Request time is every statement added up, plus every gap between them. Thirty queries at two milliseconds each is sixty milliseconds of pure waiting before a single byte gets serialized, and each one of those statements looks healthy in the slow query log. Nothing there is slow. The request still is.
Then there is the time before the query runs at all. Connection checkout queues behind whoever is holding a pool slot, and the classic holder is a transaction left open across an outbound HTTP call. Database idle, pool empty, and the latency shows up nowhere in database metrics: it happened outside the database.
And there is the time after the rows arrive: materializing objects, filtering permissions row by row, serializing nested payloads. That is application CPU, and in a worker process it blocks everything else on that worker.
So the fourth thing is the response contract itself. An endpoint with no bound on what it returns gets slower as your largest account grows, and no index fixes that.
What I instrument per request: query count, time inside the database, connection wait, serialization time. Four numbers, and the guilty one usually stands out.
I write up more of these production trade-offs here: https://polycratia.com/c/a0912ff4
Next time you chase a slow endpoint, check which of the four actually owns the latency...