Is it my API or the third-party that's slow?
Group your request timings by host and the answer falls out: if your origin’s p95 is 80ms while api.stripe.com is contributing 600ms per call, the third party is your bottleneck — and no amount of optimizing your own code will move the number users feel. The mistake is measuring only the endpoint you wrote and treating everything it calls as invisible.
Two places third-party time hides
Client-side calls (browser → analytics, fonts, payment widgets) are visible in DevTools and in any capture proxy: each external host shows up as its own requests with its own timings. Server-side calls (your endpoint calls OpenAI, then responds) are sneakier — from the outside they’re just part of your TTFB, so your endpoint looks slow while the real time is spent waiting on someone else’s API.
Attributing it properly
- Per-host breakdown for client traffic: capture a real session and rank hosts by total time consumed. A page that feels slow while your origin answers in 60ms usually has one external host eating half the waterfall. Lobe’s session view does this grouping automatically (first-party vs third-party is tagged per request).
- Server-Timing for server-side calls: wrap your upstream calls and report them —
Server-Timing: stripe;dur=610, db;dur=25. Now your 700ms TTFB confesses which 610ms wasn’t yours. - Measure the third party directly: probe the dependency’s endpoint on its own schedule. If Stripe’s p95 from your machine degrades week over week, that’s evidence for a vendor conversation — or a caching layer.
The keep-alive trap
A subtle way third parties look slower than they are: your own HTTP client’s connection handling. If your server opens a fresh HTTPS connection for every call to an external API, you pay DNS + TCP + TLS (often 100–300ms to a remote host) on top of the provider’s actual response time. Check the phase breakdown of those outbound calls: nonzero TLS time on every request means the fix is a pooled/keep-alive client, not switching vendors.
Set a dependency budget
Once attribution is clean, make it a rule instead of a one-off investigation: each external dependency gets a latency budget (e.g. “payments ≤300ms p95, or we render optimistically”), and anything over budget triggers a decision — cache it, move it off the critical path (queue + webhook), or time-box it with a fallback. Third parties will be slow sometimes; the difference between a resilient app and a slow one is whether that slowness was budgeted for.