Claude Agent SDK Hosting: Droplet or App Platform?
We earn commissions when you shop through the links below, at no extra cost to you. We only link products we would use ourselves.
The Claude Agent SDK is not a stateless API wrapper, and that one fact decides where it should live. Every query() spawns a claude binary that owns a shell, a working directory, and a transcript on local disk, and stays alive for the whole session. Host it like a web app and the first redeploy deletes every session you had.
Short answer for DigitalOcean: a Droplet for long-running agents that hold many sessions, App Platform only for one-shot or resumable sessions, and in that second case a SessionStore is mandatory, not optional. The rest of this page is the evidence: what the SDK needs from a host, what each DigitalOcean shape actually provides, what we measured on a real session, and a tested minimal host you can deploy either way. Verified September 14, 2026 against the Agent SDK hosting, session storage, quickstart and TypeScript reference pages, DigitalOcean's App Platform pricing, limits, Scale to Zero and app spec pages, the Droplet pricing page, and SDK v0.3.270 installed here.
What the SDK needs from a host
Anthropic's hosting page is unusually direct about this, so we will be too.
- One session, one subprocess. N concurrent sessions are N processes, each with its own process tree and transcript. They inherit your app's working directory unless you pass a distinct
cwdper session. - Three kinds of state on local disk, none of which survive a container restart, scale-down or move: session transcripts under
~/.claude/projects/(orCLAUDE_CONFIG_DIR/projects/),CLAUDE.mdmemory files, and whatever the agent writes into its working directory. - A sizing floor, not a ceiling: 1 GiB RAM, 5 GiB disk and 1 CPU per agent for a fresh instance. Memory grows with session length and tool activity.
- Outbound HTTPS to
api.anthropic.com(or your Bedrock, Vertex or Foundry endpoint), plus whatever your MCP servers need. Inbound is your HTTP server's problem; the subprocess never listens on the network. - No built-in session timeout. Bound sessions with
maxTurnsor a subprocess recycles only when you recycle it.
The Linux x64 binary package the SDK pulls in is 223,981,629 bytes unpacked (213.6 MiB) on npm at v0.3.270. That matters for App Platform's image-size guidance below.
What we measured
We installed @anthropic-ai/[email protected] into a clean directory on a Windows 11 x64 machine and ran one query with maxTurns: 1, settingSources: [], the default tool set, the haiku model alias, and a prompt asking for the single word "OK". We captured the subprocess PID through the spawnClaudeCodeProcess option and sampled its working set every 500 ms. Windows numbers, so treat them as the shape of the cost, not the Linux figure.
| Measurement | Result |
|---|---|
Install size (node_modules, all packages) | 246.9 MiB, of which claude.exe is 216.5 MiB |
Spawn to init message (cold) | 7,974 ms |
Spawn to result message | 9,882 ms (the model call itself: 1,737 ms) |
| Peak working set of the subprocess | 238.9 MiB, no child processes observed |
| Transcript written for that one turn | 203,878 bytes (one JSONL file) |
| Tokens on the first turn | 10 input, 25,850 written to the prompt cache, 45 output |
| SDK-reported cost of the one-word reply | $0.054 |
Three things follow. The docs' 1 GiB floor is generous for an idle session, which is exactly why it is called a floor: the number to size against is peak RSS at your real session length, and you have to measure that yourself. An 8-second cold start is why startup() exists; it spawns and completes the initialize handshake before a prompt arrives. And a single trivial turn leaves 200 KB on disk, so any host with a small ephemeral filesystem needs a plan for transcripts before it needs anything else. The 25,850 cached tokens are the fixed per-session prompt (system prompt plus tool definitions) and they are why turn two of the same session cost us $0.004 rather than $0.05; the prompt caching guide covers what keeps that cache warm.
The two DigitalOcean shapes, priced
Both are billed per second with a one-minute minimum and a 28-day monthly cap. Prices from the Droplet pricing page and the App Platform pricing docs as of today, RAM-matched:
| RAM | Droplet (Basic, Regular) | App Platform shared CPU | App Platform dedicated CPU |
|---|---|---|---|
| 1 GiB | $6 (1 vCPU) | $10 fixed, or $12 with manual scaling | $34 |
| 2 GiB | $12 (1 vCPU) or $18 (2 vCPUs) | $25 | $39 |
| 4 GiB | $24 (2 vCPUs) | $50 (2 shared vCPUs) | $49 (1 vCPU) or $78 (2 vCPUs) |
| 8 GiB | $48 (4 vCPUs) | not offered on shared | $98 (2 vCPUs) or $156 (4 vCPUs) |
Per gigabyte of RAM, which is the resource the SDK consumes, a Droplet costs roughly half of App Platform's shared tier. The difference buys you deploys from a Git push or a container image, TLS and a hostname, health checks, restarts, and no SSH to look after. Whether that is worth it depends entirely on the next section.
Where App Platform breaks the SDK's assumptions
Every item below is from DigitalOcean's own limits page, and each one lands on something the hosting page says the SDK relies on.
The filesystem is ephemeral and small. Local data "is permanently lost after deployments and other container replacements", the filesystem is capped at 4 GiB, and a container that fills it is marked unhealthy and replaced. Volumes are not supported. So the transcript from every session lives until your next git push, and at 200 KB per short session the 4 GiB cap is a real number, not a theoretical one. If you do not need to resume sessions, pass persistSession: false and nothing is written. If you do, mirror them with a SessionStore adapter: the SDK ships reference adapters for S3, Redis and Postgres, and the S3 one talks to any S3-compatible bucket. Note the docs' warning that the store mirrors transcripts only; CLAUDE.md memory and working-directory artifacts need their own sync.
The sandbox is gVisor, and some syscalls are unsupported. Anthropic's secure-deployment page lists gVisor as a supported isolation layer for the SDK, and App Platform runs every container under it. We have not run the bundled binary under App Platform's runtime, so we cannot tell you whether your agent's tools hit an unsupported call; we can tell you that is the first thing to smoke-test.
AMD64 only. The SDK's binary is selected per platform at install time. Build the image on, or for, linux/amd64, or the startup error is "native binary exists but failed to launch".
Image size. DigitalOcean recommends images under 1 GiB and warns that images over 2 GiB "are likely to experience build and deployment issues". A Node base image plus the 213 MiB binary fits, but only once; if your package manager ignores npm's libc field (Yarn 1.x does) you get both the glibc and musl binaries, and the docs' fix is to delete the one you do not run on.
Scale to Zero is not what you might assume. It exists, it bills a sleeping web service at 10% of its price, and the inactivity window is 600 to 86,400 seconds. It is also a private preview you request through Support, web services only, and a wake is a cold start of "several seconds" before the SDK's own 8-second subprocess start. For an agent that answers a chat message, that is a long silence.
No SSH. You debug through logs and the web console, which is fine until a subprocess wedges and you want ps and kill.
Where a Droplet fits
The hosting page names a "long-running sessions" pattern: a persistent host, several SDK subprocesses at once, sessions pinned to the host that holds their process. A Droplet is that shape with no translation. Disk persists across your deploys, so the default transcript location just works, the binary runs on a normal kernel, and the sizing formula from the docs is arithmetic you can do on the pricing table:
agents per host = (host RAM - overhead) / (per-session RAM ceiling)
At the docs' 1 GiB floor, the $24 4-GiB Droplet holds three agents with room for the OS and your server. Our idle measurement says the true ceiling is lower than 1 GiB for short sessions, but memory "grows with session length and tool activity", so measure a representative long session before you pack a host tighter than the floor suggests.
What you take on is the process manager, the reverse proxy, and the OS. We wrote up the Droplet preparation, the non-root agent user, the sandbox packages and the systemd unit in the unattended VPS guide; the same steps apply, the timer is just replaced by a long-running service.
Decision table
| Your session pattern | Host | Why |
|---|---|---|
| One-shot tasks, nothing to resume | Either; App Platform if you want deploy-on-push | Set persistSession: false and the ephemeral disk is irrelevant |
| Sessions that resume after idle gaps | App Platform plus a SessionStore | Per-second billing suits idle-heavy workloads; the store makes the ephemeral disk survivable |
| Many long-running sessions on one host | Droplet | Local disk persists, half the price per GiB, you can recycle subprocesses yourself |
| You do not want to run any of this | Managed Agents | Anthropic's hosted REST API, a separate product from the SDK |
The minimal host, tested
This server maps one HTTP session id to one SDK session and streams the SDK's messages back as NDJSON. We ran it locally with AGENT_MODEL=haiku, sent two turns to the same session id, and the second turn resumed the first: same session_id, the fact from turn one recalled, 25,858 tokens read from cache and 477 written, $0.004.
// server.mjs
import http from "node:http";
import fs from "node:fs";
import path from "node:path";
import { query } from "@anthropic-ai/claude-agent-sdk";
const PORT = Number(process.env.PORT || 8080);
const WORK_ROOT = process.env.WORK_ROOT || "/work";
const sessions = new Map(); // our session id -> SDK session_id
http.createServer(async (req, res) => {
if (req.method === "GET" && req.url === "/health") {
res.writeHead(200, { "content-type": "application/json" });
return res.end(JSON.stringify({ ok: true, sessions: sessions.size }));
}
const m = req.method === "POST" && req.url.match(/^\/sessions\/([A-Za-z0-9_-]{1,64})\/messages$/);
if (!m) { res.writeHead(404); return res.end(); }
let body = "";
for await (const chunk of req) body += chunk;
const { prompt } = JSON.parse(body || "{}");
if (!prompt) { res.writeHead(400); return res.end("prompt required"); }
const cwd = path.join(WORK_ROOT, m[1]);
fs.mkdirSync(cwd, { recursive: true });
res.writeHead(200, { "content-type": "application/x-ndjson" });
try {
for await (const msg of query({
prompt,
options: {
cwd,
resume: sessions.get(m[1]),
model: process.env.AGENT_MODEL,
maxTurns: 20,
settingSources: [],
env: { ...process.env, CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1" },
},
})) {
if (msg.type === "system" && msg.subtype === "init") sessions.set(m[1], msg.session_id);
res.write(JSON.stringify(msg) + "\n");
}
} catch (err) {
res.write(JSON.stringify({ type: "error", message: err.message }) + "\n");
}
res.end();
}).listen(PORT, "0.0.0.0", () => console.log(`agent host on :${PORT}`));
Two deliberate choices. settingSources: [] plus CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 is the docs' multi-tenant isolation minimum, so one caller's CLAUDE.md cannot leak into another's session. And there is no authentication, on purpose: the hosting page says the agent "should receive pre-authenticated requests and should not be the component that validates user tokens". Put a gateway in front of it before it sees the internet.
The container image, which we could not build on this machine (no Docker here) and which follows the SDK's install rules rather than our test:
FROM node:22-slim
WORKDIR /app
COPY package.json package-lock.json ./
# Do not add --omit=optional: the claude binary is an optional dependency.
RUN npm ci --omit=dev
COPY server.mjs ./
ENV PORT=8080 WORK_ROOT=/work
RUN mkdir -p /work
EXPOSE 8080
CMD ["node", "server.mjs"]
And the App Platform spec that deploys it, using the field names from DigitalOcean's app spec reference:
name: agent-host
services:
- name: web
github:
repo: you/agent-host
branch: main
deploy_on_push: true
dockerfile_path: Dockerfile
http_port: 8080
instance_count: 1
instance_size_slug: apps-s-1vcpu-2gb
health_check:
http_path: /health
initial_delay_seconds: 10
envs:
- key: ANTHROPIC_API_KEY
scope: RUN_TIME
type: SECRET
value: sk-ant-...
We picked the 2 GiB slug rather than the 1 GiB floor because this server runs the Node host and every concurrent session in one container. On a Droplet the same server.mjs runs under a systemd service with WORK_ROOT on the local disk and nothing else changes.
FAQ
Can the Claude Agent SDK run on DigitalOcean App Platform at all?
Yes, with the caveats above. It is a Linux AMD64 container that spawns a process, which App Platform allows. What it cannot do is keep local state across deploys, so treat every session as lost unless a SessionStore mirrors it, or disable persistence with persistSession: false. We have not tested the bundled binary under App Platform's gVisor runtime, so smoke-test your tools there first.
How much RAM does one Agent SDK session need?
Anthropic's starting point is 1 GiB, 5 GiB of disk and 1 CPU per agent, stated as a floor. Our one-turn session on Windows peaked at 238.9 MiB of working set. Memory grows with session length and tool use, so the docs' advice is to run a representative session to your target length and record peak RSS.
Is a Droplet or App Platform cheaper for a single agent?
For one always-on agent at the 1 GiB floor, a Droplet is $6 per month and App Platform is $10 or $12. At 4 GiB it is $24 against $49 to $50. App Platform gets cheaper only when the service sleeps: Scale to Zero bills 10% while asleep, but it is a private preview for web services and adds a cold start on top of the SDK's own subprocess start.
Should I use Managed Agents instead?
If you want none of this, yes. Anthropic's overview lists Managed Agents as a separate hosted product where Anthropic runs the agent and the sandbox behind a REST API. The SDK is for when you need your own infrastructure, isolation or data plane, which is the premise of this article. The SDK comparison covers the licensing and architecture side of that choice.
Verified September 14, 2026 against code.claude.com/docs (Agent SDK hosting, session storage, quickstart, secure deployment, troubleshooting and TypeScript reference), DigitalOcean's App Platform pricing, limits, Scale to Zero, app spec and Dockerfile reference pages, the Droplet pricing page, npm metadata for @anthropic-ai/[email protected] and its linux-x64 package, and two local runs of the SDK described above. We have not deployed this server to either DigitalOcean product; the measurements are local, the platform facts are the vendors'.