> elevenlabs-deploy-integration

Deploy ElevenLabs TTS applications to Vercel, Fly.io, and Cloud Run. Use when deploying ElevenLabs-powered apps to production, configuring platform-specific secrets, or setting up serverless TTS. Trigger: "deploy elevenlabs", "elevenlabs Vercel", "elevenlabs Cloud Run", "elevenlabs Fly.io", "elevenlabs serverless", "host TTS API".

fetch
$curl "https://skillshub.wtf/jeremylongshore/claude-code-plugins-plus-skills/elevenlabs-deploy-integration?format=md"
SKILL.mdelevenlabs-deploy-integration

ElevenLabs Deploy Integration

Overview

Deploy ElevenLabs TTS/voice applications to cloud platforms. Covers Vercel (serverless), Fly.io (containers), and Google Cloud Run with proper secrets management, timeout configuration, and streaming support.

Prerequisites

  • ElevenLabs API key for production
  • Platform CLI installed (vercel, fly, or gcloud)
  • Application code tested locally

Instructions

Vercel Deployment (Serverless)

Key constraint: Vercel functions have a 10-second timeout on Hobby (30s on Pro). Use Flash model for speed.

# Set secrets
vercel env add ELEVENLABS_API_KEY production
vercel env add ELEVENLABS_API_KEY preview

# Deploy
vercel --prod

API Route (Next.js / Vercel):

// app/api/tts/route.ts
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { NextResponse } from "next/server";

export const runtime = "nodejs";
export const maxDuration = 30; // Vercel Pro max

const client = new ElevenLabsClient();

export async function POST(req: Request) {
  const { text, voiceId = "21m00Tcm4TlvDq8ikWAM" } = await req.json();

  if (!text || text.length > 5000) {
    return NextResponse.json(
      { error: "Text required, max 5000 characters" },
      { status: 400 }
    );
  }

  try {
    const audio = await client.textToSpeech.convert(voiceId, {
      text,
      model_id: "eleven_flash_v2_5",  // Fast for serverless
      output_format: "mp3_22050_32",
      voice_settings: {
        stability: 0.5,
        similarity_boost: 0.75,
      },
    });

    return new Response(audio as any, {
      headers: {
        "Content-Type": "audio/mpeg",
        "Cache-Control": "public, max-age=3600",
      },
    });
  } catch (error: any) {
    const status = error.statusCode || 500;
    return NextResponse.json(
      { error: error.message || "TTS generation failed" },
      { status }
    );
  }
}

vercel.json:

{
  "env": {
    "ELEVENLABS_API_KEY": "@elevenlabs_api_key"
  },
  "functions": {
    "app/api/tts/route.ts": {
      "maxDuration": 30
    }
  }
}

Fly.io Deployment (Container)

Better for long-running TTS, WebSocket streaming, and high concurrency.

fly.toml:

app = "my-tts-service"
primary_region = "iad"

[env]
  NODE_ENV = "production"
  # Use the closest region to ElevenLabs servers (US East)
  ELEVENLABS_MODEL = "eleven_multilingual_v2"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

  [http_service.concurrency]
    type = "requests"
    hard_limit = 25
    soft_limit = 20

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 512
# Set secrets
fly secrets set ELEVENLABS_API_KEY=sk_your_prod_key
fly secrets set ELEVENLABS_WEBHOOK_SECRET=whsec_your_secret

# Deploy
fly deploy

# Check logs
fly logs

Express server with streaming:

// server.ts
import express from "express";
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { Readable } from "stream";

const app = express();
app.use(express.json());

const client = new ElevenLabsClient();

// Streaming TTS endpoint
app.post("/api/tts/stream", async (req, res) => {
  const { text, voiceId = "21m00Tcm4TlvDq8ikWAM", modelId } = req.body;

  res.setHeader("Content-Type", "audio/mpeg");
  res.setHeader("Transfer-Encoding", "chunked");

  try {
    const stream = await client.textToSpeech.stream(voiceId, {
      text,
      model_id: modelId || "eleven_flash_v2_5",
      output_format: "mp3_22050_32",
    });

    // Pipe streaming audio directly to response
    const readable = Readable.fromWeb(stream as any);
    readable.pipe(res);
  } catch (error: any) {
    if (!res.headersSent) {
      res.status(error.statusCode || 500).json({ error: error.message });
    }
  }
});

// Health check
app.get("/health", async (_req, res) => {
  try {
    const user = await client.user.get();
    res.json({
      status: "healthy",
      quota: {
        used: user.subscription.character_count,
        limit: user.subscription.character_limit,
      },
    });
  } catch {
    res.status(503).json({ status: "unhealthy" });
  }
});

app.listen(3000, () => console.log("TTS service running on :3000"));

Google Cloud Run

# Build and deploy
gcloud run deploy tts-service \
  --source . \
  --region us-central1 \
  --platform managed \
  --allow-unauthenticated \
  --set-secrets=ELEVENLABS_API_KEY=elevenlabs-api-key:latest \
  --timeout=60 \
  --concurrency=10 \
  --min-instances=0 \
  --max-instances=5

# Store secret in Secret Manager first
echo -n "sk_your_prod_key" | gcloud secrets create elevenlabs-api-key --data-file=-

Dockerfile:

FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "dist/server.js"]

Platform Comparison for ElevenLabs

FeatureVercelFly.ioCloud Run
Max timeout30s (Pro)No limit60min
WebSocket streamingLimitedFull supportFull support
Cold start~1-3s~0.5-2s~1-5s
ConcurrencyPer-functionPer-VMPer-instance
Best forSimple TTS APIStreaming/WebSocketVariable load
Min costFree tier~$2/moFree tier

Error Handling

IssueCauseSolution
Vercel timeoutTTS > 10s on HobbyUpgrade to Pro (30s) or use Flash model
Cold start slowContainer initializationSet min_instances=1 (Cloud Run) or min_machines=1 (Fly)
Secret not foundMissing platform configAdd via platform CLI
Streaming brokenProxy bufferingDisable response buffering in nginx/CDN
CORS errorsMissing headersAdd Access-Control-Allow-Origin to TTS endpoint

Resources

Next Steps

For webhook handling, see elevenlabs-webhooks-events.

┌ stats

installs/wk0
░░░░░░░░░░
github stars1.7K
██████████
first seenMar 23, 2026
└────────────

┌ repo

jeremylongshore/claude-code-plugins-plus-skills
by jeremylongshore
└────────────