Deploying AI Agents: Serverless vs Long-Lived Workers
Choose the right AI agent deployment model: serverless functions vs long-lived workers. Covers state, timeout limits, cost, and production AI agents.

Most teams reach for a serverless function the first time they deploy an AI agent. It's the default in 2026: cheap at rest, zero ops overhead, scales from zero. Then the function times out mid-run, the agent loses its tool-call history, and the entire task silently fails. That failure isn't bad luck. It's the architectural mismatch at the core of AI agent deployment.
Serverless functions were designed around one assumption: requests are short, stateless, and independently repeatable. AI agents violate all three. A planning agent loops over tools for several minutes, accumulates context across calls, and can't safely be retried from the start if it was halfway through writing to a database. The platform model and the workload model are fundamentally at odds.
The decision between serverless and long-lived workers is the real infrastructure choice you need to make before writing a single line of agent code. Getting it wrong costs you in failed runs, duplicate side effects, and debugging sessions that reveal almost nothing because the execution environment was already torn down.
What you'll learn
- Why serverless and agents clash by design
- What long-lived workers actually give you
- Comparing the two models side by side
- When serverless is still the right call
- Durable execution as a middle path
- State management across deployment models
- Observability requirements by runtime type
- Frequently Asked Questions
Why serverless and agents clash by design
Serverless functions have hard timeout limits. AWS Lambda maxes out at 15 minutes. Cloudflare Workers cut you off at 30 seconds on their default tier (CPU time, not wall-clock). Vercel Functions give you 60 seconds on Pro. These limits weren't designed to be obstacles, and for 99% of API workloads they're irrelevant. But an agent that calls four tools in sequence, waits for a database write, then makes two more LLM calls to synthesize the result can easily hit 3-8 minutes of real elapsed time.
Even if you squeeze within the timeout, statelessness causes the next problem. Serverless functions don't share memory between invocations. Each cold start is a blank slate. Agents, by contrast, build up a message history, track which tools they've already called, and use prior observations to decide what to do next. If you're storing all of that in the function's local memory and the function is recycled between steps, you've lost the agent's working memory.
The retry semantics compound this. Serverless platforms treat function failures as retriable by default. But agent actions often aren't idempotent. An agent that half-completed a database write or sent a notification can't simply be run again from the top without causing duplicate effects. You need to think carefully about which steps in your agent loop are safe to retry and which need a compensating action.
What long-lived workers actually give you
A long-lived worker is a process that stays resident between requests. In practice this means a container on ECS, a worker on Fly.io, a Kubernetes pod, or a Node.js process on a VPS that receives tasks from a queue. The process holds its own in-memory state, keeps database connections warm, and has no platform-imposed execution timeout.
For agents, this translates to three concrete advantages. You can hold the full message history in process memory and append to it cheaply, with no serialization to a database on every tool call. The agent loop runs as a single function call with no external orchestration coordinating steps, which makes it simpler to trace and cancel. And you can implement a clean shutdown on SIGTERM that checkpoints agent state before the process exits, giving you controlled recovery rather than silent failure.
The trade-off is real, though: you're paying for that process whether it's handling an agent task or sitting idle. For a workload that gets one agent request per hour, a long-lived worker is expensive compared to serverless. The economics only favor persistent processes when you have sustained, frequent agent tasks that justify keeping the process warm.
Scaling also shifts from automatic to manual. Serverless scales to thousands of concurrent executions without configuration. Long-lived workers require you to set up autoscaling policies, define concurrency limits per worker, and handle queue backpressure. That's ops work you don't have with serverless.
Comparing the two models side by side
| Dimension | Serverless Functions | Long-Lived Workers |
|---|---|---|
| Max execution time | 15-60 seconds to 15 minutes | Unlimited |
| In-memory state | Cleared on each invocation | Persists across tasks |
| Cold start penalty | 100ms to 3s depending on runtime | None (process already warm) |
| Cost at idle | Zero | Continuous (even if idle) |
| Retry semantics | Platform-managed, often automatic | Application-controlled |
| Horizontal scaling | Automatic, near-instant | Requires autoscaling config |
| Debugging | Log-based, ephemeral context | Full process introspection |
| Idempotency risk | High for multi-step agents | Manageable with checkpoints |
The table makes the choice look obvious, but real workloads are rarely at the extremes. A research agent that runs for 8 minutes every time is a clear fit for long-lived workers. A triage agent that classifies a support ticket in 20 seconds is a clear fit for serverless. The hard cases are in the middle.
When serverless is still the right call
Don't abandon serverless for agents wholesale. It's the right default when your agent tasks are genuinely short, deterministic, and stateless between invocations. Classification agents, extraction agents, and summarization agents often fall here: they receive a document, run one or two LLM calls with tool use, and return a structured result well within any platform's timeout, with no state that needs to persist.
Single-step agents also fit serverless well. If your "agent" is really a chain of two LLM calls with a tool lookup in the middle, calling it an agent is a stretch. That's a serverless workload dressed up in agent terminology.
Serverless makes sense when you want to scale to zero between bursts of requests. A batch processing job that triggers agents for each item in a queue every night doesn't need to pay for a worker sitting idle for 20 hours. Serverless invocations per item, with a short per-item timeout, are cheaper and simpler.
The practical rule we use at Laxaar: if your agent's P95 execution time is under 4 minutes and none of its tool calls produce non-idempotent side effects, start with serverless. You can always migrate to workers when you hit limits.
Durable execution as a middle path
Durable execution platforms (Temporal, Cloudflare Durable Objects with DO workflows, AWS Step Functions, and Inngest) offer a third option that sits between pure serverless and persistent workers. They let you write an agent loop as ordinary code, but the platform checkpoints state after each step and can resume from the checkpoint if the process dies.
You pay per step rather than per idle second, and a crashed step doesn't lose the agent's context because the platform holds it. That's a good fit for agents that need long execution times but run infrequently.
// Temporal workflow wrapping an agent loop
import { proxyActivities, sleep } from '@temporalio/workflow';
import type * as activities from './activities';
const { callLLM, executeTool } = proxyActivities<typeof activities>({
startToCloseTimeout: '5 minutes',
retry: { maximumAttempts: 3 },
});
export async function agentWorkflow(task: string): Promise<string> {
const messages: Message[] = [{ role: 'user', content: task }];
for (let step = 0; step < 20; step++) {
const response = await callLLM(messages);
messages.push({ role: 'assistant', content: response });
if (response.stop_reason === 'end_turn') {
return response.content;
}
const toolResult = await executeTool(response.tool_call);
messages.push({ role: 'tool', content: toolResult });
}
throw new Error('Max steps reached without completion');
}
The honest limitation is complexity. Temporal needs its own server plus a worker process, and the SDK integration isn't trivial. Step Functions have a verbose JSON/YAML definition language that's painful to maintain. For a team shipping its first agent, that overhead probably isn't justified. But for production agents handling critical business workflows, durable execution is worth the setup cost.
State management across deployment models
The deployment choice cuts deepest in state management. Every agent accumulates state across its run: message history, tool call results, intermediate reasoning, and external references like document IDs or session tokens.
With serverless, you're forced to externalize all of this state. Redis is the common choice for message history: fast reads and writes, with built-in TTL for expired sessions. A NoSQL store like DynamoDB works for structured checkpoints. The agent fetches its full context at the start of each invocation and writes it back at the end or after each tool call.
// Serverless agent step: load and save state from Redis
export async function handler(event: AgentEvent) {
const state = await redis.get(`agent:${event.sessionId}`);
const messages: Message[] = state ? JSON.parse(state) : [];
messages.push({ role: 'user', content: event.input });
const response = await llmClient.complete({ messages, tools });
messages.push({ role: 'assistant', content: response });
await redis.setex(`agent:${event.sessionId}`, 3600, JSON.stringify(messages));
return response;
}
With long-lived workers, you hold state in process memory and write to external storage only at checkpoints, typically after completing a logical phase of the agent's work rather than after every message. This reduces I/O significantly for long runs but requires careful cleanup logic to avoid memory leaks when handling many concurrent agent sessions.
Observability requirements by runtime type
Debugging a failing agent is already harder than debugging a conventional API, and the deployment model determines how much harder.
Serverless agents need structured logging from day one. The execution environment is ephemeral — once a Lambda function exits, its local state is gone. Emit a structured log event for every significant agent decision: tool call initiated, tool response received, next action chosen. Correlate these with a session ID so you can reconstruct the full decision trace from CloudWatch or Datadog after the fact.
Long-lived workers give you more introspection options. You can attach a debugger to the running process, inspect in-memory state, and stream traces to an observability tool in real time. The Laxaar team typically wires Langfuse or Arize Phoenix for LLM-specific traces and standard OTLP spans for the surrounding worker infrastructure.
Durable execution platforms produce a natural audit trail. Temporal's UI shows every workflow step, its inputs and outputs, and whether it succeeded or retried. For debugging stuck agents, this is genuinely the best observability of the three models: you don't need to reconstruct anything because the execution history is stored by the platform.
Regardless of runtime, you should treat each agent session as a trace with spans, not a bag of log lines. Our work on AI agent development has consistently shown that teams who instrument at the trace level debug incidents in minutes rather than hours.
If you're still deciding on an agent framework before worrying about deployment, see our breakdown at AI agent development services. For teams ready to build production-grade pipelines, the custom software development team can scope the infrastructure alongside the agent logic.
For a deeper look at cost patterns in agentic systems, the post on AI agent development cost covers where budgets actually go in production.
Frequently Asked Questions
Can you run an AI agent on a serverless function at all?
Yes, but only for short-lived, stateless tasks. Agents that classify, extract, or summarize within a single LLM call fit serverless well. Agents that loop over multiple tool calls, maintain conversation history across steps, or run for more than a few minutes don't fit without significant external state infrastructure and careful timeout management.
What's the cheapest way to deploy an agent that runs infrequently?
For infrequent workloads (say, a few runs per day), serverless is almost always cheapest because you pay zero when idle. If individual runs exceed your platform's timeout, durable execution with Temporal or Inngest is the next step: you still pay per step rather than per idle second, and you get checkpointed state for long runs.
How do you handle an agent that needs to call slow external APIs mid-run?
This is a common source of timeout failures on serverless. If the external API call can take 10-30 seconds, factor that into your timeout budget. If it can take longer, either move to a long-lived worker or use a durable execution pattern where the slow API call is its own retryable activity with a generous per-step timeout independent of the overall serverless function limit.
Does container-based deployment count as a long-lived worker?
Yes. A Docker container running your agent code on ECS, Cloud Run, or Fly.io is a long-lived worker for these purposes (even Cloud Run's minimum-instance-one setting qualifies). What makes it "long-lived" is that the process persists across requests rather than being torn down after each invocation.
Is durable execution worth the operational overhead for a small team?
For most teams shipping their first production agent, it's probably not. Start with either serverless (for short agents) or a simple worker process on a managed container platform (for long agents). Introduce durable execution when you've hit the concrete problems it solves: execution failures mid-run, timeout limits, or the need to replay and audit specific agent steps.
If you're planning an agent deployment and aren't sure which runtime fits your workload, the Laxaar team reviews the execution pattern, state model, and cost profile together before recommending an infrastructure approach. Reach out through our contact page or start with a project quote to scope what your specific agent needs.
Working on something like this?
Get a fixed scope, timeline, and price within one business day — no obligation.


