Tips > AI & LLM Integration

Handle LLM Rate Limits with Retry and Exponential Backoff

LLM APIs enforce rate limits and return HTTP 429 (Too Many Requests) when you exceed them.

LLM APIs return HTTP 429 when you exceed their rate limits, which is inevitable in batch workflows. Enable Retry On Fail on the node for a fixed-interval retry, or wrap the call in a Code node for true exponential backoff with jitter. A short Wait node between iterations self-throttles the workflow to stay under the limit.

Why do LLM API calls hit rate limits?

LLM APIs enforce rate limits and return HTTP 429 (Too Many Requests) when you exceed them. In batch workflows that process hundreds of items, hitting rate limits is not a possibility -- it is a certainty. Configure retry behavior proactively rather than discovering failures in production.

Real-world example: A workflow processes 500 customer feedback items through GPT-4o for sentiment analysis. Without retry logic, the workflow fails at item 87 when the rate limit kicks in.

How do you configure retries on a node?

n8n node-level retry settings (available on any node via Settings tab):

Setting Value
Retry On Fail Enabled
Max Retries 5
Wait Between Retries (ms) 1000

Warning: n8n uses fixed-interval retries. n8n's built-in retry mechanism uses a fixed wait interval between attempts -- it does not have a built-in exponential backoff option. For true exponential backoff, use a Code node wrapper as shown below.

How do you add exponential backoff?

For exponential backoff, use a Code node with manual retry logic:

const items = $input.all();
const results = [];

for (const item of items) {
  let attempts = 0;
  let success = false;

  while (attempts < 5 && !success) {
    try {
      // Your API call would go here via $helpers or HTTP request
      results.push({ json: { ...item.json, status: 'processed' } });
      success = true;
    } catch (error) {
      attempts++;
      if (error.message.includes('429') && attempts < 5) {
        // Exponential backoff with jitter
        const delay = Math.pow(2, attempts) * 1000 + Math.random() * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        results.push({ json: { ...item.json, status: 'failed', error: error.message } });
        success = true; // exit loop, log failure
      }
    }
  }
}

return results;

Tip: Batch Size Control. If you are processing items in a loop, add a Wait node with a 200-500ms delay between iterations. This "self-throttles" the workflow to stay under rate limits. Cheaper than retries.

Proactive rate limit handling is the difference between a workflow that runs reliably at scale and one that fails unpredictably.

Related: Use Manual Trigger During Development Instead of Webhook or Schedule · Flatten Deeply Nested API Responses

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

190 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book an introductory call