← Back to research
Guides19 min readPublished 2026-07-21

Gemini API Rate Limits and 429 Errors: Fixes for Production (2026)

Fix Gemini API 429 and quota errors: backoff, tier routing Flash vs Pro, concurrency limits — one OpenAI-compatible key on LumeAPI.

By LumeAPI Engineering Team

Gemini API hub → Cheap Gemini API →

Last verified: July 21, 2026

Short path: Gemini models and rates on Gemini API. Slow + expensive Pro misuse: Gemini API too expensive.

Production Gemini API integrations return 429 Too Many Requests, quota-exceeded errors, or throttling when traffic exceeds requests per minute (RPM), tokens per minute (TPM), or concurrent streaming connections. These are capacity signals — not model refusals based on prompt content.

Through LumeAPI, Gemini models use OpenAI-compatible Chat Completions at https://api.lumeapi.site/v1 with catalog ids like gemini-3-flash, gemini-3.5-flash, and gemini-3.1-pro-preview. Retry logic, queueing, and tier routing are your application’s responsibility.

LumeAPI is an independent gateway — not Google.

Quick Answer

SymptomLikely causeFirst fix
429 only during traffic spikesBurst exceeds RPM/concurrencySemaphore + exponential backoff
429 all day on one keyBatch + realtime share quotaSplit keys or queue batch
Slow responses and 429Pro tier for volume workDefault to 3.5 Flash
429 on streaming onlyToo many parallel SSE connectionsCap open streams per tenant
Quota exceeded (daily)Token budget exhaustedSpread jobs; downgrade default tier

Starting retry policy: 3–5 attempts, exponential backoff with jitter, honor Retry-After when present, never retry 401/400 unchanged.

Cross-provider patterns: handle LLM 429 in production. OpenAI-specific: OpenAI 429 guide.

How Gemini rate limits work (conceptually)

text
Client burst
  → gateway / upstream quota check
  → 429 + optional Retry-After header
  → client must slow down or queue

Limits may apply at multiple layers:

  • Account / API key — shared across all services using that key
  • Model family — Pro vs Flash may have different throughput profiles
  • Streaming — each open SSE connection may count toward concurrency
  • Tokens — large contexts burn TPM faster than small chat turns

Exact numbers depend on your account tier and provider — load-test your deployment instead of assuming documentation from a different vendor account applies 1:1.

Gemini tiers and when limits bite

TierCatalog id (LumeAPI)LumeAPI in/out per 1MThroughput posture
Volumegemini-3-flash$0.15 / $0.60Highest fan-out, routing, tags
Defaultgemini-3.5-flash$0.30 / $1.20Chat, agents, most production
Hardgemini-3.1-pro-preview$1.00 / $6.00Long context, failed Flash evals

Using Pro for everything increases cost and often increases latency under load — see Pro vs Flash and why Gemini feels slow.

Python retry with backoff (Gemini via LumeAPI)

python
import os
import random
import time
from openai import OpenAI, RateLimitError, APIStatusError

client = OpenAI(
    api_key=os.environ["LUMEAPI_KEY"],
    base_url="https://api.lumeapi.site/v1",
    timeout=90.0,
    max_retries=0,
)

def gemini_complete(
    messages: list,
    model: str = "gemini-3.5-flash",
    max_attempts: int = 5,
):
    delay = 0.5
    for attempt in range(max_attempts):
        try:
            return client.chat.completions.create(
                model=model,
                messages=messages,
                max_tokens=2048,
            )
        except RateLimitError as exc:
            if attempt == max_attempts - 1:
                raise
            retry_after = None
            if exc.response is not None:
                retry_after = exc.response.headers.get("retry-after")
            sleep = float(retry_after) if retry_after else delay + random.uniform(0, 0.3)
            time.sleep(min(sleep, 60))
            delay = min(delay * 2, 30)
        except APIStatusError as exc:
            if exc.status_code >= 500 and attempt < max_attempts - 1:
                time.sleep(delay + random.uniform(0, 0.3))
                delay = min(delay * 2, 30)
                continue
            raise

Do not retry invalid model ids or auth failures — fix configuration instead.

Concurrency limiting (prevent 429 before retry)

python
import asyncio

# Tune from load tests — start conservative
GEMINI_SEM = asyncio.Semaphore(15)

async def bounded_gemini(messages, model="gemini-3.5-flash"):
    async with GEMINI_SEM:
        return await asyncio.to_thread(gemini_complete, messages, model)

For synchronous Flask/Django, use a process-wide threading.Semaphore with the same limit.

Streaming: each active stream may hold a slot until [DONE]. Cap parallel streams separately from non-streaming RPC — see Gemini Python example.

Tier fallback chain (application-level)

LumeAPI does not auto-failover models. Your code selects alternates:

python
GEMINI_CHAIN = [
    "gemini-3.5-flash",
    "gemini-3-flash",
    "gpt-5.4-mini",  # cross-provider escape hatch
]

def complete_resilient(messages):
    last_err = None
    for model in GEMINI_CHAIN:
        try:
            return gemini_complete(messages, model=model)
        except RateLimitError as e:
            last_err = e
            continue
    raise last_err

Log served_model per request. Reconcile with Usage exports.

Node.js retry sketch

javascript
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.LUMEAPI_KEY,
  baseURL: 'https://api.lumeapi.site/v1',
  maxRetries: 0,
});

export async function geminiComplete(messages, model = 'gemini-3.5-flash') {
  let delay = 500;
  for (let i = 0; i < 5; i++) {
    try {
      return await client.chat.completions.create({ model, messages, max_tokens: 2048 });
    } catch (err) {
      if (err instanceof OpenAI.RateLimitError && i < 4) {
        await new Promise((r) => setTimeout(r, delay + Math.random() * 300));
        delay = Math.min(delay * 2, 30_000);
        continue;
      }
      throw err;
    }
  }
}

429 during Gemini streaming

PhaseBehavior
Before first tokenSafe to retry whole request with backoff
Mid-stream disconnectTreat as transport failure — recover stream guide
Client cancelledAbort upstream to avoid wasted generation

Reduce parallel streams during incidents — retries without lowering concurrency cause retry storms.

Production controls checklist

  • [ ] Token bucket or semaphore per API key / tenant
  • [ ] Max parallel SSE streams (separate from RPC limit)
  • [ ] Circuit breaker — stop calling for 30–60s after N consecutive 429s
  • [ ] Alert when 429 rate > 1% over 5 minutes
  • [ ] Separate keys for batch ETL vs user-facing chat
  • [ ] Default model = 3.5 Flash, not Pro
  • [ ] Dashboard: p95 latency + 429 rate + cost per task

Monitoring metrics

Track per model id:

text
429_rate = 429_responses / total_requests
retry_rate = requests_with_retry / total_requests
cost_per_success = total_spend / successful_completions

Spikes in retry_rate often precede user-visible outages. Fix concurrency before raising max_attempts.

Gemini 429 vs other errors

HTTP / errorMeaningRetry?
429Rate / quotaYes, bounded
401Bad API keyNo
400Bad body / modelNo
408 / timeoutSlow or stalledSometimes, if idempotent
5xxGateway / upstream stressLimited backoff

FAQ

Is Gemini 429 the same as OpenAI 429?

Same HTTP semantics (slow down). Quota numbers and headers differ by provider and account — test yours.

Does Flash have higher limits than Pro?

Often Flash tiers are positioned for throughput; Pro for capability. Using Pro for high-QPS chat can hit limits sooner and cost more — tier guide.

Will a cheaper model fix 429?

Only if TPM was the bottleneck and the cheaper route has headroom. Usually you need queueing or higher quota.

Should I use SDK max_retries?

Fine for prototypes. Production should use explicit backoff + metrics — see LLM fallback.

One LumeAPI key for Gemini + GPT?

Yes. Separate logical quotas in your app even if the key is shared — multi-model Python.

Gemini slow but no 429?

Different problem — often wrong tier or long context. Read Gemini slow section.

Sources and verification