A 429 from the DeepSeek API means something different from most other vendors: DeepSeek's own current rate-limit documentation states it does not impose requests-per-minute or tokens-per-minute limits at all — the only ceiling is on concurrency, the number of requests open at the same time.
It's a concurrency cap, not a throughput cap
DeepSeek counts a request as "open" from the moment it's sent until the response finishes, and limits how many can be open simultaneously per model — not how many you send over a minute or an hour. That's a meaningfully different constraint from an RPM or TPM ceiling: a slow client sending requests one at a time, well below any throughput limit another vendor might impose, can still hit a 429 if it happens to have too many of those requests in flight at once.
The concurrency ceiling is set per model
Current documented limits differ by model — deepseek-v4-pro allows up to 500 concurrent requests, while deepseek-v4-flash and deepseek-v4-flash-vision-exp allow up to 2,500 each. A workload calling more than one of these models tracks each against its own separate ceiling, so exceeding the limit on one model says nothing about headroom on another.
There's no queueing — exceeding the cap returns an immediate 429
Unlike a vendor that queues excess requests and processes them as capacity frees up, DeepSeek returns the 429 immediately once the concurrency ceiling for a model is exceeded — the request is rejected outright rather than held. That makes client-side concurrency control the actual fix, not a smarter retry loop after the fact.
Fixing it: cap concurrency client-side, and finish requests faster
Bounding how many requests your own client keeps in flight at once — a semaphore or worker-pool cap set comfortably under the documented per-model limit — is the direct fix, since the constraint is about simultaneous open connections rather than volume over time. Because a request occupies its concurrency slot for its entire duration, anything that shortens that duration — a tighter max_tokens, avoiding unnecessarily long completions — frees slots sooner and effectively raises how much real throughput the same concurrency ceiling can support.