Cohere API 504 Gateway Timeout

Cohere's heaviest traffic is embed and rerank batches, where latency scales with the size of what you sent — which makes most Cohere 504s deterministic and reproducible rather than random.

11 min read
Staff Pick

📡 Monitor your APIs — know when they go down before your users do

Better Stack checks uptime every 30 seconds with instant Slack, email & SMS alerts. Free tier available.

Start Free →

Affiliate link — we may earn a commission at no extra cost to you

Live Cohere status right now

Settle this before anything else. A genuine Cohere incident makes the timer analysis below irrelevant — you should be failing over, not reading proxy configs.

A 504 is a statement about a clock, not about a failure. Some intermediary decided in advance how long it was willing to wait, the answer did not arrive inside that window, and the intermediary wrote an error of its own. Nothing in the status code tells you that Cohere failed. It tells you that a deadline expired, and deadlines are configuration — which means the fault is findable by reading a number rather than by guessing.

Whose clock is the whole question. It might be Cohere's edge. It might just as easily be your ingress controller, a service-mesh sidecar, a corporate egress proxy, a platform request limit, or the timeout argument you passed to your own SDK three releases ago and have not looked at since. These produce an identical status code and entirely different remediation.

30-second triage: read the elapsed time, not the status code. If your 504s cluster on a round number — 30s, 60s, 120s — that number is somebody's configured constant and your job is to find whose. If the elapsed times are scattered, something variable is being waited on. Either way, checklive Cohere statusfirst so you know whether any of this analysis is worth doing.

504 against the rest of the 5xx family

These five get filed together as “the API is broken” and then handed one retry policy, which guarantees the policy is wrong for at least three of them. The last column is the one that matters, because it is the only one that changes what you do next.

CodeWho authored itCorrect response
429Cohere, deliberately, about your allowanceSlow down. Never fail over — you export your own pacing bug
500The service, about an unhandled faultRetry once or twice; a persistent 500 is a bug report
502An intermediary, about an unusable replyIdentify the hop from the body, then one jittered retry
503The service, about having no capacityRetry with a budget, then fail over or degrade
504An intermediary, about a deadline it setFind the timer from elapsed time; retry only if idempotent

502 and 504 are the two gateway-authored codes and they are routinely conflated. The difference is simple and it changes your diagnosis: a 502 means the gateway got an answer it could not use, so the evidence is in the response body; a 504 means it got nothing and stopped waiting, so the evidence is in the elapsed time. The unusable-reply case is covered in theCohere 502 guide, the capacity case in theCohere 503 guide, and throttling in theCohere 429 guide.

📡
Recommended

Find Out Whose Timer Expired

External checks run from outside your own network on a known deadline, so a timeout inside your infrastructure looks different from one at the provider edge — instead of identical, which is what your application logs show you.

Try Better Stack Free →

Why Cohere returns 504 specifically: batch size is the independent variable

Cohere's production footprint is weighted differently from a pure chat provider. The volume lives in embed and rerank — the retrieval-augmented-generation plumbing — and those endpoints take batches. A batch is not one request that happens to be large; it is N units of work billed and processed as one call, and its latency scales with N in a way that a chat completion's simply does not.

That gives Cohere 504s a property almost no other provider's have: they are usually deterministic. The same batch that timed out will time out again. A batch half the size will very often succeed. This is enormously good news diagnostically, because a failure you can reproduce on demand is one you can bisect, and bisecting resolves in two requests what log archaeology would not resolve in an hour.

It also means the usual incident reflex is wrong here. Retrying an oversized batch unchanged simply reproduces the timeout while billing you for the attempt, and failing over to another provider re-sends the same oversized payload down a different pipe with the same result. The correct response to a size-dependent 504 is to change the size, which is a code change rather than an incident response.

Sample rather than probe once, and record all three columns. One request cannot tell a total failure apart from the far more common partial one:

for i in $(seq 1 10); do
  curl -s -o /dev/null -w "%{http_code} %{time_total}s %{content_type}\n" \
    --max-time 90 \
    https://api.cohere.com/v2/chat \
    -H "Authorization: Bearer $COHERE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"command-r-plus","messages":[{"role":"user","content":"ping"}],"max_tokens":1}'
done

The status code says whether it failed, the elapsed time says which timer expired, and the content type says who wrote the error. Set --max-time deliberately higher than the deadline you are investigating, otherwise curl becomes the shortest timer in the path and you measure your own probe instead of the system.

The Cohere trap: a deterministic size threshold is often your own egress limit

Run the bisect before anything else. Resend the failing batch at one tenth the size. If it succeeds, the failure is size-dependent and you have converted an outage investigation into a chunking task. If it fails identically, size is not the variable and you should treat it as a genuine availability question.

When the bisect does find a threshold, look carefully at where the threshold sits before blaming Cohere. Embed batches are frequently megabytes of JSON, and a clean cutoff at a round payload size — one megabyte, ten megabytes — is the fingerprint of a request-body limit in your own path: an ingress controller, an API gateway, a corporate egress proxy. Those write their own 504s and 413s and never mention the provider.

Then chunk deliberately rather than empirically. Pick a batch size comfortably below the threshold you measured, make the chunking a property of your client rather than a value someone tuned during an incident, and record the batch size on every error so the next occurrence is diagnosable from the log line alone.

The streaming case, where the 504 stops happening at all

Streaming is the most underrated fix for 504s, and it works for a reason that is easy to miss: most gateway timeouts are idle timeouts rather than total-duration limits. They fire when no bytes have moved for N seconds, not when the request has been open for N seconds. A streamed response puts bytes on the wire as soon as the first tokens exist, which resets the idle timer continuously and keeps a long generation alive under a deadline that would have killed the buffered equivalent.

  • Check which kind of timeout you have. An idle timeout is defeated by streaming; a hard request-duration cap is not. They are configured separately and confusing them wastes a day.
  • Assert on the terminal event. An iterator finishing is not the same as a stream completing. If the terminal marker never arrived, the response was truncated no matter what the status code said.
  • Count partial responses as their own class. Not a success, not a 5xx. On a streamed path they are the metric that moves first, and a status-code-only dashboard stays flat through the entire incident.
  • Decide the resume policy in advance. Re-issuing the whole prompt is the honest default and it bills twice; showing the partial output with a visible label is often the better product answer.

A retry policy that fits a 504 specifically

504 is the 5xx where the standard retry advice is most likely to hurt you, because the one thing a 504 does not tell you is whether the work happened. Four rules keep the retry from becoming its own incident:

  • Assume the request may have succeeded. Your gateway stopped listening; the upstream did not necessarily stop working. Send an idempotency key for anything with a side effect, and expect a retried completion to be billable twice.
  • Do not retry into the same deadline. If the timeout was too short for this request, a second identical attempt will expire identically. Change something — stream it, shrink it, or route it to a path with a longer deadline — or do not retry at all.
  • Budget by ratio, not by count. Allow retries as a fraction of recent successes so the allowance collapses on its own when almost everything is failing, with no deploy required. See the Cohere retry budget guide.
  • Retry against a deadline, not a counter. If the user-facing request gave up eight seconds ago, attempt three is load on behalf of nobody. Propagate the deadline and skip attempts that cannot finish inside it.

If 504s persist past a couple of attempts they have stopped being transient, and the failover machinery should take over — which only works if it was kept warm. TheCohere failover guidecovers keeping a second path tested rather than merely configured, and thecircuit breaker guidecovers stopping the retries automatically.

Frequently Asked Questions

What does a 504 from the Cohere API actually mean?

It means an intermediary between your process and the model set a deadline, that deadline expired before a usable response arrived, and the intermediary wrote its own error rather than waiting longer. Two things follow, and both are frequently missed. First, the 504 was authored by whichever hop was holding the timer — which may be Cohere's edge, but may equally be your own load balancer, service mesh, egress proxy or SDK client. Second, a 504 says nothing about whether the upstream completed the work; it says only that the answer did not come back inside the window. That distinction is what makes the retry decision non-obvious.

How is a 504 different from a 502 on Cohere?

They are siblings — both are written by intermediaries, neither is authored by the component that actually failed — but they describe opposite events. A 502 means the gateway received something it could not use: an empty body, a reset connection, a malformed reply. A 504 means the gateway received nothing at all and gave up waiting. The practical difference is what you measure next. For a 502 the diagnostic signal is the response body and its content type, because that identifies the author. For a 504 the diagnostic signal is elapsed time, because the elapsed time tells you which timer expired, and timers are configuration you can find and read.

Is a 504 the same as Cohere being down?

Usually not, and the two call for opposite responses. A real outage is broad, sustained and consistent — every endpoint, every key, every request shape. A 504 is characteristically narrow: it hits the slow requests, the large requests, or the requests that traverse one particular hop, while everything else continues to work. Sample rather than infer from a single failure. Ten identical probes failing over several minutes is an incident and failover is correct; three of ten failing while the fast requests sail through is a deadline set too tight for part of your traffic, and failing over exports the problem rather than solving it.

Is it safe to retry a Cohere 504?

Less safe than a 502, and the reason is worth understanding rather than memorising. A 504 means the answer did not arrive in time — it does not mean the upstream never did the work. The request may have completed a moment after your gateway stopped listening, which for a completion is a billing question and for anything with a side effect is a correctness one. Retry only what is idempotent, or propagate an idempotency key so the second attempt is provably the same operation rather than a second one. And retry against a deadline rather than a fixed count: if the user-facing request gave up already, attempt three is load on behalf of nobody.

Why do my Cohere 504s show up as client-side timeout exceptions instead of status codes?

Because whichever timer is shortest wins, and it is often yours. If your SDK's client timeout is below the gateway's, your process abandons the request first and raises a local exception — the 504 that the gateway would eventually have written never reaches you, and your status-code dashboard stays clean through the whole incident. This is why the elapsed-time distribution matters more than the error taxonomy here. Log total elapsed time on every failure, timeouts included, and count local timeouts in the same bucket as 504s; otherwise you are measuring which timer fired rather than how often requests failed.

My Cohere embed call times out consistently on the same input. Is Cohere down?

A consistently reproducible failure is almost never an outage — outages are broad and indiscriminate, and they do not single out one payload. What you are describing is the signature of size-dependent latency, which is the normal failure mode for batch endpoints: the batch is large enough that processing it exceeds a deadline somewhere in the path, so it fails every time in exactly the same way. Resend it at a tenth of the size. If that succeeds, you have your answer in one request, and the fix is chunking rather than anything an incident channel needs to hear about.

Should I retry a timed-out Cohere rerank batch?

Not unchanged, because you already know what will happen. A batch that exceeded a deadline once will exceed it again, so an unmodified retry is a request you are paying for and can predict the outcome of. Retry smaller instead — split the batch and send the halves — which both usually succeeds and tells you where the threshold is. Reserve ordinary retry-with-backoff for the case where the failures are not reproducible on the same input, because that is the only case where the transient assumption the retry is built on actually holds.

Related Cohere Guides

Know Whose Deadline Expired — Before Your Users Do

API Status Check watches Cohere and the rest of your stack from outside your own network on a known deadline, so you find out whether the timer that fired was theirs or yours — in seconds, not after twenty minutes of reading a status page that was never going to mention it.

Start Your Free Trial →

Alert Pro

14-day free trial

Stop checking — get alerted instantly

Alert Pro checks the 60+ APIs we monitor every hour and emails you within the hour of a detected change.

  • Email alerts for up to 10 of the APIs we monitor
  • $0 charged today — card required to start
  • Cancel anytime — $9/mo after trial

🌐 Can't Access Cohere?

If Cohere is working for others but not for you, it might be an ISP or regional issue. A VPN can help bypass network-level blocks and routing problems.

🔒

Troubleshoot with a VPN

Connect from a different region to test if the issue is local to your network. Also protects your connection on public Wi-Fi.

Try NordVPN — 30-Day Money-Back Guarantee
🔑

Secure Your Cohere Account

Service outages are a common time for phishing attacks. Use a password manager to keep unique, strong passwords for every account.

Try NordPass — Free Password Manager
Quick ISP test: Try accessing Cohere on mobile data (Wi-Fi off). If it works, the issue is with your ISP or local network.

⏳ While You Wait — Try These Alternatives

🛠 Tools We Use & Recommend

Tested across our own infrastructure monitoring 200+ APIs daily

SEMrushBest for SEO

SEO & Site Performance Monitoring

Used by 10M+ marketers

Track your site health, uptime, search rankings, and competitor movements from one dashboard.

We use SEMrush to track how our API status pages rank and catch site health issues early.

From $129.95/moTry SEMrush Free
View full comparison & more tools →Affiliate links — we earn a commission at no extra cost to you