Agent Skills: ElevenLabs Rate Limits

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/elevenlabs-rate-limits

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/elevenlabs-pack/skills/elevenlabs-rate-limits

Skill Files

Browse the full folder contents for elevenlabs-rate-limits.

Download Skill

Loading file tree…

plugins/saas-packs/elevenlabs-pack/skills/elevenlabs-rate-limits/SKILL.md

Skill Metadata

Name
elevenlabs-rate-limits
Description
|

ElevenLabs Rate Limits

Overview

Handle ElevenLabs rate limits with plan-aware concurrency queuing, exponential backoff, and quota monitoring. ElevenLabs uses two rate limit mechanisms: concurrent request limits (per plan) and system-level throttling. The key insight is that a 429 means two different things depending on its detail.status — and each demands the opposite response.

Prerequisites

  • ElevenLabs SDK installed (@elevenlabs/elevenlabs-js)
  • Understanding of your subscription plan's limits
  • p-queue package (recommended): npm install p-queue

Instructions

Step 1: Understand the Two 429 Error Types

ElevenLabs returns HTTP 429 for two different reasons. Read the detail.status field to tell them apart — the correct strategy is opposite for each.

| 429 Variant | Response Body | Cause | Strategy | |-------------|--------------|-------|----------| | too_many_concurrent_requests | {"detail":{"status":"too_many_concurrent_requests"}} | Exceeded plan concurrency | Queue requests, don't backoff | | system_busy | {"detail":{"status":"system_busy"}} | Server overload | Exponential backoff |

Step 2: Know Your Plan Concurrency Limits

Concurrency is capped per plan. Size your queue to this number — never higher.

| Plan | Max Concurrent Requests | Characters/Month | |------|------------------------|-------------------| | Free | 2 | 10,000 | | Starter | 3 | 30,000 | | Creator | 5 | 100,000 | | Pro | 10 | 500,000 | | Scale | 15 | 2,000,000 | | Business | 15 | Custom |

Step 3: Assemble the Four Building Blocks

Write four small modules and compose them. The full, copy-ready source for each is in references/implementation.md — the skeleton below shows how they fit together.

  1. Request queue (rate-limiter.ts) — a p-queue sized to your plan's concurrency limit. This is the response to too_many_concurrent_requests: queue, do not back off.
  2. Backoff wrapper (backoff.ts) — exponential backoff with jitter for system_busy and 5xx; immediate short retry for concurrency; hard-fail on 401/400/404.
  3. Quota monitor (quota-monitor.ts) — polls user.subscription character usage, warns at a threshold, and blocks a request that would overrun remaining quota.
  4. Resilient client (resilient-client.ts) — composes all three so one generateSpeech() call guards quota, queues, and backs off automatically:
// src/elevenlabs/resilient-client.ts (skeleton — full source in references/implementation.md)
export function createResilientClient(plan = "pro") {
  const client = new ElevenLabsClient({ maxRetries: 0 }); // we handle retries
  const queue = createRequestQueue(plan);                 // Step 3.1
  const quota = new QuotaMonitor(client);                 // Step 3.3

  return {
    async generateSpeech(voiceId, text, modelId = "eleven_multilingual_v2") {
      await quota.guardRequest(text.length);              // Step 3.3
      return queue.add(() =>                              // Step 3.1
        withBackoff(() =>                                 // Step 3.2
          client.textToSpeech.convert(voiceId, { text, model_id: modelId })
        )
      );
    },
  };
}

Step 4: Mind Model Cost When Managing Quota

Quota is spent in credits-per-character, which varies by model. Use Flash/Turbo models during development to conserve quota.

| Model | Credits per Character | 10,000 Chars Cost | |-------|-----------------------|-------------------| | eleven_v3 | 1.0 | 10,000 credits | | eleven_multilingual_v2 | 1.0 | 10,000 credits | | eleven_flash_v2_5 | 0.5 | 5,000 credits | | eleven_turbo_v2_5 | 0.5 | 5,000 credits |

Output

Applying this skill produces four TypeScript modules under src/elevenlabs/ and a rate-limited request path:

  • rate-limiter.ts — exports createRequestQueue(plan) returning a plan-sized PQueue.
  • backoff.ts — exports withBackoff(operation, config) returning the operation's result or throwing after maxRetries.
  • quota-monitor.ts — exports a QuotaMonitor class with check(){ used, limit, remaining, pctUsed, warning } and guardRequest(textLength).
  • resilient-client.ts — exports createResilientClient(plan) whose generateSpeech() returns TTS audio, plus getQueueStats() and checkQuota().

At runtime: concurrent requests stay at or below the plan cap, system_busy responses are retried with backoff, and requests that would overrun quota fail fast with a clear error instead of a wasted API call.

Error Handling

| Scenario | Detection | Response | |----------|-----------|----------| | Concurrent limit hit | 429 + too_many_concurrent_requests | Queue; retry after ~50ms per queued request | | System busy | 429 + system_busy | Exponential backoff (1s, 2s, 4s, 8s...) | | Quota exhausted | 401 + quota_exceeded | Stop requests; alert; wait for reset | | Server error | 500-599 | Exponential backoff; max 5 retries |

Examples

Concise starting point — batch generation with just the queue:

import { createRequestQueue } from "./elevenlabs/rate-limiter";

const queue = createRequestQueue("pro"); // 10 concurrent
const clips = await Promise.all(
  texts.map(text =>
    queue.add(() => client.textToSpeech.convert(voiceId, { text, model_id: "eleven_flash_v2_5" }))
  )
); // 20 requests, at most 10 in flight

For the full resilient-client example, per-429-variant branching at the call site, and the batch pattern in context, see references/examples.md.

Resources

Next Steps

For security configuration, see elevenlabs-security-basics.