If an endpoint lands on almost exactly three seconds no matter the payload, that is not slow code: that is a per-attempt timeout multiplied by a retry count.
Real work gives you a distribution. Small inputs finish faster, large ones slower, p99 drifts away from p50. A configuration constant gives you a flat line instead. So when latency stops reacting to data volume, quit profiling queries and go read the retry policy.
The pattern I keep finding in payment and verification integrations: a provider call sitting right in the request path with a one-second timeout and three attempts. The provider never refuses. It hangs, or it answers slowly under its own load. Each attempt burns its full budget, the last one succeeds or a fallback returns something usable, and the endpoint reports success. Nothing gets logged as an error, because nothing failed. The retry layer quietly converted an availability problem into a latency problem.
How I handle it now: one deadline for the whole operation, propagated down, instead of per-attempt timeouts that silently add up. I retry only what is genuinely retryable (a provider's validation rejection will reject three times just as politely). And attempt count becomes a first-class metric rather than a debug line, because that number is the latency.
I wrote the longer version up on my blog: https://polycratia.com/c/4732c933
The last slow endpoint you chased, it is worth knowing whether that time went on working or on waiting...