polycratia

Cutting an API from three seconds to 200 milliseconds is rarely a performance win. Usually it is an admission that the endpoint was doing someone else's work synchronously, on your caller's clock.

Here is the shape it takes in the systems I build. A request arrives, and inside the handler it fans out to third parties: carrier rate quotes, then a verification provider, then a payment status lookup on top of that. Each call is acceptable on its own. Serialized inside one request they stack, and your p95 now belongs to the slowest external party on their worst day.

No amount of query tuning fixes that. Indexes do not make someone else's API faster.

The fix is changing what the endpoint promises. Pull the fan-out out of the request path. Refresh carrier rates on a schedule and serve them from a local table with an explicit freshness stamp. Turn "go ask the provider for status" into "read the status recorded when their webhook arrived". Return what you already own, not what you have to go fetch.

That trade has a price, and it is worth naming. Two things keep it honest.

The response has to carry how old the data is, so callers can decide whether stale is acceptable for their use case. A shipping estimate tolerates minutes. A compliance check usually does not.

The write path has to be idempotent, because you are now recording state from retries and webhooks that will arrive more than once, out of order, and occasionally contradicting each other.

Miss the first and you serve wrong data quickly and quietly. Miss the second and you get duplicate state that surfaces weeks later in reconciliation, which is a much more expensive bug than a slow endpoint.

The latency number is the side effect. The real change is that your endpoint stops failing when a third party has a bad afternoon: you degrade to slightly older data instead of timing out.

I have written up more of these production trade-offs on my blog: https://polycratia.com/c/38d85f48

If you have made this move, the first thing that broke was probably one of two things: readers who needed fresher data than you assumed, or duplicate writes from webhook retries...

react

$ new-project --brief

or email hey@polycratia.com