API त्रुटि 429 Too Many Requests: सीमाएं, Retry-After और सुरक्षित बैकऑफ
LLM API में HTTP 429 त्रुटियों को हल करने के लिए डेवलपर गाइड: RPM/TPM सीमा विश्लेषण, Retry-After पढ़ना और एक्सपोनेंशियल बैकऑफ कोड लागू करना।
विषय-सूची
API त्रुटि 429 Too Many Requests: सीमाएं, Retry-After और सुरक्षित बैकऑफ
HTTP 429 Too Many Requests त्रुटि तब उत्पन्न होती है जब कोई क्लाइंट API प्रदाता द्वारा निर्धारित अनुरोध आवृत्ति या टोकन सीमा को पार कर जाता है। बिना सोचे-समझे तुरंत पुनः प्रयास (retry) करने से समस्या हल नहीं होती, बल्कि यह ‘रिट्राई स्टॉर्म’ (retry storm) उत्पन्न करके खाते को लंबे समय तक अवरुद्ध कर देती है।
अपने एप्लिकेशन की स्थिरता बहाल करने के लिए, डेवलपर्स को सीमा के प्रकार (RPM, TPM या बैलेंस समाप्ति) की पहचान करनी चाहिए, Retry-After हेडर को सही ढंग से पार्स करना चाहिए और रैंडम जिटर के साथ एक्सपोनेंशियल बैकऑफ (Full Jitter Exponential Backoff) लागू करना चाहिए।
LLM API में HTTP 429 त्रुटि के कारण
आधुनिक भाषा मॉडल API (जैसे OpenAI, Anthropic और संगत गेटवे) में 429 स्थिति कोड मुख्य रूप से तीन कारणों से आता है:
- RPM (Requests Per Minute): प्रति मिनट अनुरोधों की संख्या की सीमा। यह तब होता है जब बिना कतार नियंत्रण के समानांतर कई अनुरोध भेजे जाते हैं।
- TPM (Tokens Per Minute): एक मिनट की अवधि में कुल इनपुट और आउटपुट टोकन की सीमा। लंबे संदर्भ या बड़े प्रॉम्प्ट भेजने पर यह सीमा जल्दी समाप्त हो जाती है।
- कोटा या बैलेंस की समाप्ति: प्रीपेड बैलेंस शून्य होने या निर्धारित खर्च सीमा तक पहुंचने के कारण रुकावट।
HTTP/1.1 429 Too Many Requests
Date: Sun, 23 Aug 2026 03:00:00 GMT
Content-Type: application/json
Retry-After: 6
x-ratelimit-limit-requests: 500
x-ratelimit-remaining-requests: 0
x-ratelimit-reset-requests: 6s
x-ratelimit-limit-tokens: 30000
x-ratelimit-remaining-tokens: 1200
x-ratelimit-reset-tokens: 150ms
{
"error": {
"message": "Rate limit reached for model in organization on tokens per minute (TPM). Please try again in 6s.",
"type": "tokens",
"param": null,
"code": "rate_limit_exceeded"
}
}
जब त्रुटि बैलेंस समाप्ति या 5-घंटे की सदस्यता सीमा के कारण होती है, तो स्वचालित पुनः प्रयास केवल नेटवर्क बैंडविड्थ बर्बाद करते हैं। जटिल लॉग का विश्लेषण किए बिना मूल कारण को तुरंत समझने के लिए, BetterToken एक पारदर्शी डैशबोर्ड प्रदान करता है: यह वास्तविक समय में HTTP स्थिति कोड, इनपुट/आउटपुट/कैश टोकन का सटीक विवरण और पे-ऐज़-यू-गो बैलेंस दिखाता है बिना किसी 5-घंटे के लॉकआउट के।
429 त्रुटि निदान तालिका
| लक्षण | मुख्य कारण | प्रतिक्रिया में क्या जांचें | इंजीनियरिंग समाधान |
|---|---|---|---|
| समानांतर अनुरोधों पर विफलता | RPM सीमा पार | x-ratelimit-remaining-requests: 0 | सेमाफोर या कतार के माध्यम से समानांतरता सीमित करें |
| लंबे प्रॉम्प्ट पर विफलता | TPM सीमा पार | x-ratelimit-remaining-tokens < प्रॉम्प्ट आकार | संदर्भ को अनुकूलित करें, प्रॉम्प्ट कैशिंग चालू करें या बैच विभाजित करें |
| 100% अनुरोधों पर 429 | बैलेंस / कोटा समाप्त | insufficient_quota त्रुटि कोड | पुनः प्रयास रोकें और बैलेंस रिचार्ज करें या कुंजी जांचें |
| 429 त्रुटियों में भारी वृद्धि | रिट्राई स्टॉर्म | Retry-After हेडर की अनदेखी | प्रतीक्षा समय में रैंडम जिटर (Jitter) जोड़ें |
Retry-After हेडर को सही ढंग से पार्स करना
RFC 6585 विनिर्देश के अनुसार, Retry-After हेडर दो मानक प्रारूपों में प्रतीक्षा समय प्रदान करता है:
- सापेक्ष सेकंड (पूर्णांक या दशमलव, उदा.
Retry-After: 12) - HTTP-Date टाइमस्टैम्प (उदा.
Retry-After: Sun, 23 Aug 2026 03:05:00 GMT)
import datetime
import email.utils
import time
def parse_retry_after(header_value: str | None, default_delay: float = 1.0) -> float:
if not header_value:
return default_delay
header_value = header_value.strip()
try:
return max(0.0, float(header_value))
except ValueError:
pass
try:
parsed_date = email.utils.parsedate_to_datetime(header_value)
now = datetime.datetime.now(datetime.timezone.utc)
delay = (parsed_date - now).total_seconds()
return max(0.0, delay)
except Exception:
return default_delay
Full Jitter एक्सपोनेंशियल बैकऑफ लागू करना
यदि Retry-After हेडर अनुपस्थित है, तो जिटर के साथ एक्सपोनेंशियल बैकऑफ का उपयोग करें। प्रयास $i$ के लिए प्रतीक्षा समय की गणना:
$$T_{ ext{wait}} = ext{random}(0, \min(T_{ ext{max}}, T_{ ext{base}} imes 2^i))$$
import asyncio
import json
import random
import httpx
class RateLimitRetryClient:
def __init__(
self,
base_url: str = "https://www.bettertoken.ai/v1",
api_key: str = "",
max_retries: int = 4,
base_delay: float = 1.0,
max_delay: float = 32.0,
):
self.base_url = base_url
self.api_key = api_key
self.max_retries = max_retries
self.base_delay = base_delay
self.max_delay = max_delay
self.client = httpx.AsyncClient(
base_url=self.base_url,
headers={"Authorization": f"Bearer {self.api_key}"},
timeout=60.0,
)
async def send_chat_completion(self, payload: dict) -> dict:
for attempt in range(self.max_retries + 1):
try:
response = await self.client.post("/chat/completions", json=payload)
if response.status_code == 200:
return response.json()
if response.status_code == 429:
error_data = response.json().get("error", {})
error_code = error_data.get("code")
if error_code in ("insufficient_quota", "billing_not_active"):
raise RuntimeError(f"बिलिंग त्रुटि: {error_data.get('message')}")
if attempt == self.max_retries:
raise RuntimeError(f"अधिकतम पुनः प्रयास सीमा समाप्त (429): {response.text}")
retry_after = response.headers.get("Retry-After")
if retry_after:
wait_time = parse_retry_after(retry_after) + random.uniform(0.1, 0.5)
else:
backoff_cap = min(self.max_delay, self.base_delay * (2 ** attempt))
wait_time = random.uniform(0, backoff_cap)
await asyncio.sleep(wait_time)
continue
response.raise_for_status()
except httpx.RequestError as exc:
if attempt == self.max_retries:
raise
wait_time = min(self.max_delay, self.base_delay * (2 ** attempt))
await asyncio.sleep(wait_time)
raise RuntimeError("पुनः प्रयास बजट समाप्त होने के बाद अनुरोध विफल रहा")
सुरक्षा और पुनः प्रयास में सावधानी
रीड-ओनली (GET) अनुरोधों को दोहराना सुरक्षित है। लेकिन LLM अनुमान वाले POST अनुरोधों के लिए:
- डुप्लिकेट निष्पादन रोकें: यदि नेटवर्क टाइमआउट होता है, तो दोबारा भेजने से पहले जांचें कि टोकन खर्च हुए या कार्य पूरा हुआ या नहीं।
- क्लाइंट रिक्वेस्ट आईडी का उपयोग करें: लॉग में ट्रैक करने के लिए
X-Request-IDहेडर शामिल करें। - 401/403 को 429 न समझें: प्रमाणीकरण त्रुटियों को ठीक करने के लिए API कुंजी बदलनी होगी, इंतजार नहीं करना होगा।
रिकवरी सत्यापन
पूरा ट्रैफ़िक फिर से शुरू करने से पहले:
- न्यूनतम टोकन (
max_tokens: 5) के साथ एक परीक्षण अनुरोध भेजें। - HTTP 200 प्राप्त होने और
x-ratelimit-remaining-requestsहेडर की पुष्टि करें। - त्रुटि दर की निगरानी करते हुए धीरे-धीरे समानांतर अनुरोध बढ़ाएं।
कठोर मिनट सीमाओं के कारण अचानक होने वाली 429 रुकावटों से बचने और अनुरोधों पर पूर्ण नियंत्रण रखने के लिए, BetterToken API पर स्विच करें, समर्पित API कुंजियां बनाएं और डैशबोर्ड में रीयल-टाइम टोकन उपयोग की निगरानी करें।