Claude API Serverless Function Deployment on Vercel
Deploying Claude API calls as Vercel serverless functions
If you're searching for this, you're probably trying to put a Claude-powered endpoint behind a Vercel deployment without spinning up a dedicated backend. The short answer: create an API route (or Edge Function) in your Next.js or standalone Vercel project, call the Claude API from it server-side, and let Vercel handle scaling, HTTPS, and routing for you. The tricky parts are streaming responses through serverless infrastructure, managing execution time limits, and keeping your API key out of the client bundle.
This guide walks through a working deployment, the specific constraints Vercel imposes on long-running or streaming requests, and how to decide whether you need raw Anthropic access or a wrapped API that's easier to operate at scale.
Setting up the project structure
A typical setup is a Next.js app with an API route under app/api/claude/route.js (App Router) or pages/api/claude.js (Pages Router). Either works; App Router is the current default for new Vercel projects.
// app/api/claude/route.js
export async function POST(req) {
const { prompt } = await req.json();
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
}),
});
const data = await response.json();
return Response.json(data);
}
Store the key as an environment variable in the Vercel dashboard (Settings > Environment Variables), not hardcoded. Never expose it in a client component — the whole point of a serverless function here is to act as a secure proxy between the browser and the model provider.
Choosing Edge vs Node runtime
Vercel functions run on either the Node.js runtime or the Edge runtime. This matters for Claude API calls:
- Node runtime — default, supports the full Node API surface, better for complex logic, has a configurable
maxDuration(up to 300s on Pro plans, less on Hobby). - Edge runtime — lower cold-start latency, runs closer to the user, but has a stricter 25-second execution limit and a reduced API surface (no native
fs, limited npm compatibility).
If you're doing short, non-streaming completions, Edge is fine. For anything involving longer generations, tool use loops, or streaming a long response, Node with an explicit duration config is safer:
export const maxDuration = 60; // seconds, Node runtime only
Handling streaming on Vercel
Streaming is where most deployments go wrong. Claude's API supports server-sent events, but serverless platforms buffer responses differently depending on runtime and hosting layer. On Vercel, streaming works correctly when you return a ReadableStream directly from the route handler instead of collecting the full response first:
export async function POST(req) {
const { prompt } = await req.json();
const upstream = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
stream: true,
messages: [{ role: "user", content: prompt }],
}),
});
return new Response(upstream.body, {
headers: { "content-type": "text/event-stream" },
});
}
This forwards the upstream stream directly instead of waiting for completion, which avoids hitting function timeouts on longer generations and gives the client tokens as they arrive.
Cold starts and function limits to plan around
A few practical constraints to design around when deploying Claude calls as Vercel functions:
- Timeout ceilings — Hobby plan functions cap at 10 seconds, Pro at 60 by default (configurable up to 300). Long tool-use chains or large-context requests can blow through this.
- Cold starts — first invocation after idle time adds latency. Edge functions mitigate this better than Node for simple requests.
- Payload size — Vercel functions have request/response body limits (typically 4.5MB for Node functions), which matters if you're passing large documents or images in the request.
- Concurrency — each request spins up its own function instance; there's no built-in connection pooling or rate limiting across invocations, so a traffic spike can hit Anthropic's rate limits simultaneously across many cold-started functions.
That last point is the one teams underestimate. A Vercel function that calls Claude directly has no shared state between invocations, so retry logic, rate-limit backoff, and usage tracking all have to be built per-request or pushed into a separate layer.
When a managed API layer is simpler than raw Anthropic calls
If you're deploying multiple projects or a team product on Vercel, routing every function directly to Anthropic means re-implementing key management, retries, and usage visibility in every repo. SubToAPI sits in front of your existing Claude access and exposes it as a standard HTTPS API with its own sub_live_... application keys, so your Vercel functions call one stable endpoint instead of juggling provider-specific auth and rate limit handling per deployment.
A Vercel route calling SubToAPI instead of Anthropic directly looks almost identical:
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
}),
});
The difference is what happens around that call: usage metadata per key, team seats if multiple developers deploy functions against the same account, and one dashboard instead of scattered environment variables across projects. See the quickstart and streaming docs for the exact request/response shapes, which mirror the Messages API closely enough that migrating an existing Vercel function usually means changing the base URL and auth header.
FAQ
Can I call the Claude API directly from a Vercel Edge Function?
Yes, as long as the request completes within Edge's execution limit (around 25 seconds) and you're not relying on Node-only APIs. For longer generations or tool-use loops, use the Node runtime with an extended maxDuration instead.
How do I stream Claude responses through a Vercel function without buffering?
Return the upstream fetch response's body directly as a ReadableStream from your route handler rather than awaiting .json() first. This forwards server-sent events as they arrive instead of waiting for the full completion.
Do I need a separate backend, or can Vercel functions handle this alone?
For a single project, serverless functions on Vercel are usually enough. If you're deploying Claude access across multiple projects or teams, a managed layer like SubToAPI handles key management and usage tracking centrally so you're not duplicating that logic in every function.