Rate limiting protects both the gateway and the upstream providers behind it. When you
exceed a limit the AIWave API returns 429 Too Many Requests. This page
explains how to detect it, how to back off correctly, and how to structure a workload so you rarely hit
the ceiling at all.
A 429 carries the standard error envelope:
{
"error": {
"message": "Rate limit exceeded",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}
A 429 can also mean the account balance is exhausted rather than a request-rate problem.
Check the console before assuming it is throughput.
Retrying immediately makes congestion worse. Back off exponentially and add jitter so that many clients do not retry in lockstep.
import time, random
from openai import OpenAI, APIStatusError
client = OpenAI(api_key="sk-YOUR_KEY", base_url="https://aiwave.live/v1")
def with_backoff(fn, attempts=6, base=1.0, cap=32.0):
for i in range(attempts):
try:
return fn()
except APIStatusError as e:
if e.status_code != 429 or i == attempts - 1:
raise
delay = min(cap, base * (2 ** i)) * (0.5 + random.random())
time.sleep(delay)
resp = with_backoff(lambda: client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Hello"}],
))
Most rate-limit problems are really concurrency problems. A semaphore around your worker pool is usually more effective than any retry strategy.
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI(api_key="sk-YOUR_KEY", base_url="https://aiwave.live/v1")
sem = asyncio.Semaphore(8) # tune to your workload
async def ask(prompt):
async with sem:
r = await client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": prompt}],
)
return r.choices[0].message.content
async def main(prompts):
return await asyncio.gather(*(ask(p) for p in prompts))
A 503 is not a rate limit — it means the upstream provider is overloaded, and the
right response is a fallback model rather than a longer sleep. See
error codes for the full decision table.