Gemini API 429 RESOURCE_EXHAUSTED: Quotas, Tiers and Retries
Your Gemini calls were working, then started failing with HTTP 429 and RESOURCE_EXHAUSTED. This page explains which limit you hit, why adding API keys doesn't help, how free and paid tiers differ, and how to retry without making it worse.
Quick answer
A 429 RESOURCE_EXHAUSTED means your Google Cloud project, not your API key, went over one of its rate limits for that model: requests per minute (RPM), input tokens per minute (TPM), requests per day (RPD), or a spend-based limit. Back off exponentially with jitter, and wait at least the retryDelay if the error body includes one. Then check your actual limits on the AI Studio Rate Limit page. For a lasting fix, lower your request rate or size, or move the project to a higher usage tier by linking billing.
Symptoms and What the Error Means
On the generateContent API, a quota 429 looks like this. The example below was posted by a user in googleapis/python-genai#1427:
{
"error": {
"code": 429,
"message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [{ "description": "Learn more about Gemini API quotas", "url": "https://ai.google.dev/gemini-api/docs/rate-limits" }]
}
]
}
}Some 429s also carry a suggested wait time in a google.rpc.RetryInfo detail, as shown in python-genai#1875:
{ "@type": "type.googleapis.com/google.rpc.RetryInfo", "retryDelay": "53s" }Google's generateContent error reference describes the 429 as "You've exceeded one of the API's rate limits (RPM, TPM, RPD, spend, etc.)". If you use the newer Interactions API, the code field tells you which kind of limit you hit:
Interactions API code | Meaning |
|---|---|
rate_limit_exceeded | Per-minute or per-second request or token limit |
quota_exceeded | Daily quota |
too_many_requests | Too many requests in a short period |
Don't confuse it with these neighbors:
- 402
RESOURCE_EXHAUSTED, "Your Prepay credit balance is depleted." It has the same status string but a different HTTP code. Every key on that billing account stops until credits are added. Google says not to retry it. See Insufficient Quota & 402 Billing Errors. - 503
UNAVAILABLE. Google's service is temporarily short on capacity. It isn't your quota, so backoff helps, and switching models temporarily is Google's suggested workaround. The Claude 429 vs 529 guide covers the same distinction on Anthropic's side. - 403
PERMISSION_DENIED. The project is restricted, needs verification, or the key is blocked. Retrying won't help.
Why It Happens
From Google's rate limits page:
- Three main dimensions, each enforced on its own. RPM, TPM (input) and RPD are checked independently. Google's example: with an RPM limit of 20, the 21st request in a minute fails "even if you haven't exceeded your TPM or other limits."
- Limits apply per project, not per key. Every key in the same project draws from the same quota. A second key in the same project gives you nothing extra.
- RPD resets at midnight Pacific time. A per-minute 429 clears within a minute. A daily one lasts until the reset.
- Limits differ by model. Experimental and preview models get tighter limits. Some models have extra dimensions, such as images per minute (IPM) for image models or tokens per day (TPD). Built-in tools have their own limits too: Grounding with Google Search on Gemini 3 and newer has a default of 1,500 requests per day per project.
- Spend-based limits. Paid tiers also have a spend cap measured over a rolling 10-minute window. A burst of large-context or long-output requests can trip it even when RPM looks fine.
- Batch and Priority are separate. The Batch API has its own limits (including enqueued tokens per model). Priority inference has its own limits, by default 0.3x the standard limit, and its usage still counts toward overall interactive traffic.
Google also notes that the published limits describe what you're allowed, not a promise of capacity: "actual capacity may vary."
Free Tier vs Paid Tiers
Limits are tied to the project's usage tier, and Google upgrades the tier automatically as the project qualifies:
| Tier | How a project gets there |
|---|---|
| Free | An active project or free trial; some projects need verification |
| Tier 1 | Set up and link an active Cloud Billing account |
| Tier 2 / Tier 3 | Cumulative payment thresholds plus a waiting period after the first successful payment (see the rate limits page for the current criteria) |
Points that trip people up:
- Free tier to Tier 1 usually takes effect instantly, and later upgrades within about 10 minutes. Check the current tier on the Projects page.
- Not every project or account is eligible for the free tier. Per the troubleshooting guide, creating a new key in the same project won't fix that, because eligibility is decided per project. Upgrading to paid doesn't unlock free-tier quota either.
- Some models have no free tier at all. Google states that Gemini 4 Argon "is not available on the Free tier", so call
gemini-4-argonfrom a billed project.
Fix 1: Find Out Which Limit You Hit
- Open the Rate Limit page in AI Studio and select the model. Compare your RPM, TPM and RPD usage with the limits for your tier.
- Check the Usage page for spikes, such as a retry loop or a batch job sharing the project.
- Watch how long it lasts. A 429 that clears within a minute or so points to RPM or TPM. One that keeps coming back for hours points to RPD, which resets at midnight Pacific.
Fix 2: Retry With Backoff and Honor retryDelay
The official SDKs already retry. The Python SDK, for example, retries 429 and 5xx up to four times, starting at about 1 second with a maximum of 60 seconds (troubleshooting guide). If you call REST directly, do the same thing: use exponential backoff with jitter, retry only 429, 408 and 5xx, and cap the number of attempts.
import os, random, time, requests
URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent"
HEADERS = {"x-goog-api-key": os.environ["GEMINI_API_KEY"], "Content-Type": "application/json"}
RETRYABLE = {408, 429, 500, 503, 504}
def server_retry_delay(resp):
"""Return RetryInfo.retryDelay in seconds, if the error body has one."""
try:
for d in resp.json().get("error", {}).get("details", []):
if d.get("@type", "").endswith("google.rpc.RetryInfo"):
return float(d["retryDelay"].rstrip("s"))
except (ValueError, KeyError):
pass
return None
def generate(prompt, max_retries=5):
body = {"contents": [{"parts": [{"text": prompt}]}]}
for attempt in range(max_retries + 1):
resp = requests.post(URL, headers=HEADERS, json=body, timeout=300)
if resp.ok:
return resp.json()
if resp.status_code not in RETRYABLE or attempt == max_retries:
resp.raise_for_status() # 400/402/403: fix the request, don't retry
backoff = min(60, 2 ** attempt) + random.uniform(0, 1)
time.sleep(max(backoff, server_retry_delay(resp) or 0))Two rules matter more than the exact numbers. Never retry in a tight loop, because hammering a limit you're already over just keeps you there. And if several workers share a project, add jitter so they don't all retry in the same second.
Fix 3: Lower the Load on the Dimension You're Hitting
- TPM: send less input per request. Trim conversation history, summarize old turns, and don't resend large documents on every call; context caching exists for exactly this.
- RPM: queue requests with a rate limiter set just below your limit, instead of firing them all at once and retrying.
- RPD: move offline work (evaluations, bulk classification, backfills) to the Batch API, which has its own limits apart from interactive traffic.
- Spend-based limits: spread out expensive large-context or long-output requests, or shorten outputs.
Fix 4: Raise the Limit the Supported Way
If you hit the limit during normal production use, link a billing account so the project leaves the free tier, and let the automatic tier upgrades take effect. Past that, use the paid-tier rate limit increase request linked from Google's rate limits page. Google says it reviews requests but makes no promises.
If You're Using byesu
byesu is an AI API gateway with an OpenAI-compatible endpoint: one key for Gemini, Claude, GPT and Grok, billed pay-as-you-go with no subscription. Two notes for Gemini:
- You can call Gemini through the OpenAI-compatible endpoint
https://byesu.com/v1with model IDsgemini-4-argonorgemini-3.8-flash, using the samesk-token as your other models. Your own AI Studio project tier doesn't apply to these requests. - Errors come back in OpenAI format. A rate-limit or upstream error from the gateway arrives as an OpenAI-style
{"error": {"message": ..., "type": ..., "code": ...}}body, not Google'sstatus: RESOURCE_EXHAUSTEDwithRetryInfo. Use the same backoff, and readerror.messagefor the reason.
To get started, create a token in the console and follow the Quick Start.
FAQ
What does Gemini API 429 RESOURCE_EXHAUSTED mean?
Your Google Cloud project exceeded one of its rate limits for the model you called: requests per minute (RPM), input tokens per minute (TPM), requests per day (RPD), or a spend-based limit. Exceeding any single dimension triggers the error, even if the others have room. Wait and retry with exponential backoff, or reduce request rate and size.
Does creating another API key raise my Gemini quota?
No. Gemini API rate limits are applied per project, not per API key, so every key in the same project shares one quota. Limits rise with the project's usage tier, which depends on linking a billing account and its payment history.
When does the Gemini requests-per-day quota reset?
Requests per day (RPD) quotas reset at midnight Pacific time. Per-minute limits recover continuously, so a 429 from RPM or TPM usually clears within a minute, while an RPD 429 lasts until the daily reset.
Where can I see my Gemini API rate limits?
Open the Rate Limit page in Google AI Studio (aistudio.google.com/rate-limit). It shows the active limits for your project and tier per model. The Projects page shows which usage tier each project is on, and the Usage page shows recent consumption.
Should I retry a Gemini 429 immediately?
No. Use exponential backoff with jitter, and if the error body includes a google.rpc.RetryInfo retryDelay, wait at least that long. Cap the number of retries. Do not retry 400, 402 or 403 errors; they will not succeed without a change on your side.
