all posts

How Sandbox Pricing Models Actually Work in 2026

Ajay Kumar··11 min read

Every code-execution sandbox vendor publishes a price, and almost none of them publish the number you'll actually pay. That's not a conspiracy — it's that the headline rate is one term in a formula with six other terms, and the other six are where teams get surprised. I'm Ajay; I built PandaStack, which is a sandbox platform, so I have an obvious interest in how you think about this. I'm going to try to earn your attention by doing the thing vendors usually don't: explain the pricing axes without quoting anybody's price list, including my own.

This is a buyer's guide to the economics, not a feature bake-off. By the end you should be able to open any vendor's pricing page — E2B, Modal, Daytona, Northflank, Vercel Sandbox, Fly, us, whoever — and know within five minutes which axis will dominate your bill and what to ask the sales engineer that they won't volunteer. If your workload is an AI agent, I'll spoil the answer now: idle time. An agent sandbox spends most of its life doing nothing while a model generates tokens somewhere else, and whether you pay for those seconds matters more than a 30% difference in the per-second rate.

This post names no prices, on purpose. Sandbox pricing in this category changes often and quietly — rates, free tiers, idle rules, rounding granularity, and egress terms all move. Anything I printed here would be stale before you read it, and a stale number in a blog post is worse than no number, because it looks authoritative. Verify every vendor's current published pricing against their own docs on the day you check, and date what you find. The only hard numbers below are PandaStack's own latency figures, which I can stand behind because I measure them.

Axis 1: what unit is the meter actually counting?

Everything starts here, because the unit determines which of your behaviors are free and which are expensive. Three broad shapes exist in this market, and vendors mix them.

Per-second wall-clock is the most common: you pay for every second the sandbox exists, multiplied by the resource size you reserved. Simple to reason about, brutally unforgiving of idle. Per-vCPU-second (and its sibling, per-GiB-second) unbundles the size term so a 4 vCPU box costs four times a 1 vCPU box for the same wall-clock second — same underlying idea, finer granularity, and it makes over-provisioning visibly expensive. Active-CPU-only billing is the interesting one: you pay only for seconds where the sandbox is actually burning CPU, and idle wall-clock is discounted or free. That model was built more or less specifically for the AI-agent shape of workload, and where it's genuinely offered it can change your bill by an order of magnitude.

The catch with active-CPU billing is that "active" is a vendor-defined word. Does a sandbox holding an open socket and 4 GiB of resident memory count as idle? Is memory billed at the full rate while CPU is parked? These are answerable questions, and they're in the docs, but you have to go looking. The pitch is "you only pay when your code runs." The reality is usually "full CPU rate when your code runs, and a reduced memory-retention rate the rest of the time" — still a very good deal, just not the same deal.

Axis 2: idle time, or paying a VM to watch an LLM think

This is the single largest hidden cost in agent workloads and it deserves its own section. Picture the actual timeline of one agent turn: the agent decides to run some code, the sandbox executes it in 900 milliseconds, and then the agent sends the output back to a model that spends eleven seconds streaming tokens before deciding what to do next. Repeat forty times. Under a wall-clock meter, you have just paid, per second, for a virtual machine to sit perfectly still and watch a language model think.

Run the ratio honestly for your own agent and it tends to be uncomfortable: the sandbox's actual CPU utilization across its lifetime is usually a small fraction, with the rest spent waiting on inference, on a tool call, or on a human to approve something. On a wall-clock meter, most of your compute bill may be buying you nothing at all. Nobody puts that on the pricing page, because it isn't a property of the price — it's a property of how the price interacts with your workload. Measure your own ratio; it's the single most valuable number in this exercise.

There are three structural fixes, and it's worth knowing which one you're buying. First, active-CPU billing: the vendor absorbs the idle and bills you on work done. Second, scale-to-zero or hibernate: the sandbox is suspended when idle and the meter stops, at the cost of a resume latency you have to be able to hide. Third — the one people forget — kill the sandbox and make a new one. That option is only rational if creating a sandbox is fast and cheap, which brings us directly to the next axis.

Axis 3: the cold-start tax is a pricing lever in disguise

Cold-start latency looks like a performance metric. It is actually a cost metric, and this is the most under-appreciated point in the whole post. The chain runs like this: if creating a sandbox takes several seconds, you cannot afford to create one per request, because your users will feel it. So you keep a pool of warm sandboxes ready. Warm sandboxes are running sandboxes. Running sandboxes are billed sandboxes. You are now paying, continuously, for capacity that exists solely to hide the fact that provisioning is slow.

Everything about the warm pool is a cost you didn't ask for. You size it for peak concurrency, so at 3 a.m. you're paying for a peak-shaped fleet serving a trough-shaped load. You pick a keep-alive TTL — too short and you thrash into cold starts, too long and you burn seconds on boxes nobody will use. And you build the pool manager, which is real engineering time spent solving a problem that provisioning latency created. The warm pool is the cold-start tax, paid in cash rather than milliseconds.

This is the design bet PandaStack made and it's the one place I'll be specific about numbers. There is no warm pool. Every create restores a baked Firecracker snapshot on demand — the restore step is about 49 ms, with end-to-end create at 179 ms p50 and roughly 203 ms p99. The only slow path is the first-ever spawn of a brand-new template, which cold-boots in about 3 seconds and bakes the snapshot for everyone after. When create is under 200 ms, keeping boxes warm stops being worth it: you create on demand, you kill on completion, and your idle cost is approximately zero because there is no idle. Forking works the same way — a same-host copy-on-write fork is 400–750 ms (cross-host, 1.2–3.5 s), so branching a warm state N ways doesn't mean paying to keep N boxes alive on the off chance.

The general principle survives the vendor pitch: when evaluating any platform, treat the create latency as an input to your cost model, not just your UX budget. Ask yourself honestly — at this create latency, would I run ephemeral sandboxes, or would I be forced to build a warm pool? If the answer is warm pool, add the pool's steady-state cost to that vendor's quote before comparing. It's frequently the largest line item nobody put in the spreadsheet.

Axis 4: minimum billable duration and rounding granularity

"Per-second billing" hides two separate parameters: the rounding increment and the minimum charge. A platform that rounds every sandbox up to the next full minute, or that imposes a one-minute floor per invocation, is not really billing per second for your workload if your workload is thousands of two-second executions. You're paying 30x. This is the classic serverless-billing gotcha and it migrated into the sandbox category intact.

Whether it matters depends on your lifetime distribution, so compute that first. If your mean sandbox lifetime is twenty minutes, per-second versus per-minute rounding is noise. If you run short, bursty executions — a code interpreter answering one question, a per-request evaluation, a CI shard — rounding can be the dominant term. Look for three things in the docs: the rounding increment, the minimum billable duration, and whether the meter starts at request time or at ready time. That last one is quietly important: if it starts when you call create and the platform takes four seconds to boot, you are being billed for the vendor's provisioning latency.

Axis 5: memory tiers and the OOM ratchet

Most platforms sell resources in tiers or in linear vCPU/GiB units, and either way the memory dimension has a nasty property: it's set by your worst moment, not your average one. Your agent's steady-state workload might need 512 MiB comfortably. But one build step — a webpack bundle, a tsc pass over a large monorepo, a pandas read of a fat CSV, a Next.js production build — spikes past the tier ceiling and the kernel OOM-kills it. The fix is to move up a tier. And now every sandbox you create, including the thousands that would have been fine at 512 MiB, is billed at the higher tier forever.

I know this one from the inside: PandaStack's own `base` template is baked at 4 GiB precisely because 2 GiB was OOM-killing real Next and Vite builds. That's the honest shape of the problem — memory sizing gets ratcheted upward by the tail of your workload and it never ratchets back down. There's also a structural wrinkle worth knowing if you're on any snapshot-restore platform: a restored VM's memory size is baked into the snapshot, so "just give this one sandbox more RAM" isn't always a per-request parameter. It can be a property of the image.

The practical mitigation is to segment: don't run every workload at the tier your heaviest build needs. Route builds to a large tier and routine command execution to a small one. Two templates, two sizes, two very different bills — and plenty of teams never do it, because the first tier they picked was whichever one stopped the OOM emails.

Axis 6: egress, storage, and snapshots — the add-ons people forget

Compute gets all the attention on the pricing page and then the data lines quietly accumulate underneath it. Network egress is the classic one, and code-execution workloads are unusually egress-heavy in a way that's easy to miss: every fresh sandbox that runs `pip install` or `npm ci` pulls the same tens or hundreds of megabytes from the internet, and you pay for that transfer on every single cold run. Multiply by your create volume. The fix is architectural rather than commercial — bake dependencies into your template or snapshot so the install happens once instead of ten thousand times — but you have to notice the line item before you'll bother.

Then there's persistence. Durable volumes, snapshot storage, and image storage are usually billed per GiB-month separately from compute, and snapshot storage in particular grows without anyone owning it. Every snapshot is a full memory image plus a disk image, so if your workflow snapshots liberally and cleans up never, you'll find a bill line you can't explain six months from now. Ask whether deleted sandboxes' snapshots are garbage-collected — "we keep every snapshot until you delete it" is a perfectly reasonable default that becomes an expensive one at volume.

Axis 7: concurrency caps and the enterprise-tier cliff

This one isn't a rate at all, which is exactly why it ambushes people. Many platforms cap concurrent sandboxes per plan. The per-second rate looks great, you model your bill, you sign up — and then your load spikes past the concurrency ceiling and you're not paying more, you're getting 429s. The remedy is not a bigger usage bill; it's a conversation with sales and a jump to a tier with a different pricing model entirely, often with an annual commitment. The cost curve isn't a line, it's a step function, and the step is where your negotiating leverage goes to die.

So find the caps before you commit, and find all of them: concurrent sandboxes, creates per minute, per-sandbox CPU/memory ceilings, and maximum lifetime. Then check where your projected peak sits against each. If your peak is at 70% of a plan ceiling, you are one good week of user growth away from an unplanned enterprise negotiation. For contrast at the other end: a self-hosted PandaStack agent pre-allocates 16,384 /30 subnets, so the per-host ceiling is a property of your hardware rather than your plan — which is the argument for owning the substrate, not a claim that owning it is free.

The seven axes, in one table

  • Billing unit — What it means: per-second wall-clock, per-vCPU-second, or active-CPU-only. What to watch for: whether "active" excludes memory retention, and whether size multiplies the rate.
  • Idle time — What it means: whether you pay while the sandbox waits on an LLM, a tool, or a human. What to watch for: for agents this is typically the large majority of a sandbox's lifetime, so ask explicitly — it's rarely on the pricing page.
  • Cold-start tax — What it means: slow creates force a warm pool, and warm means billed. What to watch for: add your warm pool's steady-state cost to the vendor's quote before comparing anything.
  • Rounding and minimums — What it means: the increment the meter rounds to, plus any per-invocation floor. What to watch for: a one-minute minimum on two-second executions is a 30x multiplier; also check whether the meter starts at create or at ready.
  • Memory tiers — What it means: you're sized by your worst build, not your median run. What to watch for: one OOM ratchets every future sandbox up a tier; segment builds from routine execution into separate templates.
  • Egress and storage — What it means: per-GiB network transfer plus durable volumes and images. What to watch for: repeated dependency installs on cold sandboxes pay egress on every run — bake them into the snapshot instead.
  • Snapshot/persistence storage — What it means: memory + disk images billed per GiB-month, accumulating silently. What to watch for: retention policy and whether snapshots are garbage-collected when their sandbox is deleted.
  • Concurrency caps — What it means: a plan ceiling on simultaneous sandboxes or creates per minute. What to watch for: a step function, not a curve — hitting it means a sales call and a commitment, not a bigger invoice.

A worked model: estimating your own bill

The estimate that matters is boring arithmetic over four variables you already have or can measure in an afternoon: requests per day, mean sandbox lifetime, the resource tier you reserve, and your idle ratio. Here's the model as a script you can actually run. Every number in it is a placeholder — I've made that explicit in the variable names, because the entire point of this post is that I'm not going to pretend to know your rate or your workload.

#!/usr/bin/env python3
"""Sandbox bill estimator.

EVERY number below is a PLACEHOLDER. Replace the rates with figures you
read off the vendor's CURRENT pricing page (and write down the date), and
replace the workload numbers with what you actually measure. Do not treat
the defaults as a quote for anything.
"""

# ---- YOUR WORKLOAD (measure these; don't guess twice) ------------------
REQUESTS_PER_DAY      = 20_000   # sandbox creates per day
MEAN_LIFETIME_SEC     = 90.0     # create -> kill, wall clock
ACTIVE_CPU_FRACTION   = 0.12     # share of lifetime actually burning CPU
VCPU                  = 2        # reserved size
MEM_GIB               = 4        # reserved size (set by your WORST build)
EGRESS_MB_PER_CREATE  = 40.0     # deps pulled on a cold sandbox

# ---- VENDOR TERMS (fill from their docs; PLACEHOLDER VALUES) -----------
RATE_PER_VCPU_SEC     = 0.0      # <-- put the real number here
RATE_PER_GIB_SEC      = 0.0      # <-- put the real number here
RATE_PER_GB_EGRESS    = 0.0      # <-- put the real number here
ROUNDING_SEC          = 1.0      # 1 = per-second, 60 = rounds up to a minute
MIN_BILLABLE_SEC      = 0.0      # per-invocation floor
BILLS_IDLE            = True     # False = active-CPU-only model
PLATFORM_FEE_MONTH    = 0.0      # seat/plan minimum, if any

DAYS = 30


def billable_seconds(lifetime: float) -> float:
    """Apply the idle rule, then the floor, then the rounding increment."""
    secs = lifetime if BILLS_IDLE else lifetime * ACTIVE_CPU_FRACTION
    secs = max(secs, MIN_BILLABLE_SEC)
    # Rounding is applied per invocation, which is what makes short
    # executions on a coarse increment so expensive.
    return -(-secs // ROUNDING_SEC) * ROUNDING_SEC


billable = billable_seconds(MEAN_LIFETIME_SEC)
creates = REQUESTS_PER_DAY * DAYS

compute = creates * billable * (VCPU * RATE_PER_VCPU_SEC + MEM_GIB * RATE_PER_GIB_SEC)
egress = creates * (EGRESS_MB_PER_CREATE / 1024.0) * RATE_PER_GB_EGRESS
total = compute + egress + PLATFORM_FEE_MONTH

print(f"billable sec/create : {billable:.1f} (of {MEAN_LIFETIME_SEC:.1f} wall clock)")
print(f"creates/month       : {creates:,}")
print(f"compute             : {compute:,.2f}")
print(f"egress              : {egress:,.2f}")
print(f"platform fee        : {PLATFORM_FEE_MONTH:,.2f}")
print(f"TOTAL / month       : {total:,.2f}")

# Now flip BILLS_IDLE and re-run. The delta between the two numbers is what
# you are paying for VMs to sit and watch a language model think.
# Then set ROUNDING_SEC = 60 and re-run. That delta is the rounding tax.
# If either delta is large, you have found the axis that decides your bill.

The output number is not the point. The two deltas are. Flip `BILLS_IDLE` and you've measured exactly what idle billing costs you on this workload; set `ROUNDING_SEC` to 60 and you've measured the rounding tax. Whichever delta is bigger is the axis you should be negotiating on, and the one you should let decide your vendor. If both deltas are small relative to the total, congratulations — you have a long-lived, CPU-saturated workload, the headline rate really is the whole story for you, and you can shop on price like a normal person.

Sanity-check the model against a real invoice before you trust it for anything load-bearing. Run one week of real traffic on a candidate platform, then compare the actual bill to what this script predicted. If they disagree by more than a little, you've found a term you didn't know about — which is precisely the thing you wanted to find during a trial rather than during a growth spike.

The cheapest lifecycle discipline: TTL plus an explicit kill

Whatever platform you land on, the highest-leverage cost control is embarrassingly unglamorous: stop the meter the moment the work is done, and make sure something reaps the sandbox if your process dies before it can. Two mechanisms, belt and braces. An explicit kill in a `finally` block handles the happy path and most unhappy ones. A TTL set at create time handles the case where your worker gets OOM-killed mid-turn and never runs its cleanup — without it, that sandbox bills until someone notices, which historically is "the first of the month."

from pandastack import Sandbox

# Belt: ttl_seconds is a server-side reaper. If this process dies, gets
# OOM-killed, or is redeployed mid-turn, the sandbox still goes away and
# the meter still stops. Set it to the longest turn you'd tolerate, not
# the longest you can imagine.
sbx = Sandbox.create(template="code-interpreter", ttl_seconds=300)

try:
    result = sbx.exec(
        "python /work/analyze.py --input /work/data.csv",
        timeout_seconds=120,
    )
    print("exit:", result.exit_code)
    print(result.stdout[-2000:])
finally:
    # Braces: kill it the instant the work is done. Do NOT hold the sandbox
    # open across the agent's next LLM call "in case we need it again" --
    # that is the single most expensive habit in agent infrastructure.
    # At a ~179ms p50 create, making a fresh one is cheaper than waiting.
    sbx.kill()

That comment in the `finally` block is the cost thesis of this post compressed into four lines. The instinct to hold a sandbox open between agent turns "because recreating it is expensive" is correct on a platform where create takes five seconds and wrong on one where it takes a fifth of a second. Create latency doesn't just change your latency budget — it changes which lifecycle pattern is economically rational. So check what your platform's create actually costs in time, and pick the pattern that follows from it rather than inheriting a warm-pool habit from a platform you left two years ago.

One more thing worth measuring rather than assuming: where your billable seconds actually go. If every sandbox spends 40 seconds on `npm ci` before doing 3 seconds of useful work, you're paying that tax in both billable seconds and egress, and the fix is a template with dependencies baked in — not a cheaper vendor.

# Before you shop on price, find out where your billable seconds go.
# Run this INSIDE one representative sandbox and read the split.
set -euo pipefail

start=$(date +%s.%N)
npm ci --prefer-offline
deps=$(date +%s.%N)
npm run build
build=$(date +%s.%N)
node dist/task.js
done_=$(date +%s.%N)

echo "deps  : $(echo "$deps  - $start" | bc)s"
echo "build : $(echo "$build - $deps"  | bc)s"
echo "work  : $(echo "$done_ - $build" | bc)s"

# If 'deps' dwarfs 'work', your problem is not the per-second rate --
# it's that you are paying to download the same node_modules on every
# single create. Bake it into the template or the snapshot and the
# line disappears from both your compute and your egress bill.

The four questions to ask any vendor

Sales engineers are generally happy to answer these; they're just not questions the pricing page is designed to prompt. Ask them in writing, and date the answers.

  1. Am I billed while the sandbox is idle — and what exactly counts as idle? Specifically: if my sandbox has an open connection and 4 GiB resident but zero CPU for thirty seconds, what do those thirty seconds cost? Get the memory-retention rate, not just the CPU rate.
  2. What's the rounding increment, the minimum billable duration, and when does the meter start — at my create call, or when the sandbox is ready to accept work? If it starts at my call, your provisioning latency is on my invoice.
  3. What are the hard caps on my plan — concurrent sandboxes, creates per minute, max lifetime, max memory — and what happens at the ceiling: throttling, queueing, or errors? Where does the next tier start, and is it a published price or a negotiation?
  4. What's billed outside compute? Egress, durable volumes, snapshot and image storage, and any platform or seat minimum. Then ask the follow-up: are snapshots garbage-collected when their sandbox is deleted, or do they accumulate until I clean them up?

A fifth, optional question if you're doing serious volume: what does the migration path look like if I outgrow this? An open-source substrate you can self-host, or at minimum an SDK with a configurable base URL, means the answer isn't "rewrite your integration." That's a structural cost that never appears on a pricing page and can dwarf every rate on it.

Why sub-second create changes the economics, not just the UX

Pulling the threads together, because this is the argument I actually believe and I want to state it plainly rather than smuggle it in. Sandbox cost is dominated by seconds you're billed for but doing no work in. There are only two sources of those seconds: sandboxes held open while something else is slow, and sandboxes kept warm because creating one is slow. Both are downstream of provisioning latency. Make create fast enough and both disappear — not because the rate got cheaper, but because you stopped buying the seconds.

PandaStack's version of that bet: no warm pool at all, every create restoring a baked Firecracker snapshot (~49 ms restore, 179 ms p50, ~203 ms p99 end to end), copy-on-write forks at 400–750 ms same-host so branching doesn't mean keeping N boxes alive, and templates baked with dependencies so cold sandboxes don't re-pay egress. The honest caveat: self-hosting it means you own hosts, an agent fleet, networking, and storage, and that operational weight is a real cost that a hosted meter absorbs for you. Below a certain volume, paying someone else's markup is straightforwardly the cheaper choice, and I'd rather you run the numbers than take my word for it. I wrote up where that break-even tends to sit in /blog/e2b-cost-at-scale, and the per-model billing shapes in /blog/code-interpreter-api-pricing.

The general lesson survives whichever platform you pick, and it's the thing I'd want a buyer to take away: don't shop this category on the headline rate. Shop it on idle treatment, rounding, and create latency, in that order, because those three decide the multiplier that the rate gets applied to. Then model your own workload with real numbers, verify every vendor figure against their current docs on the day you check, and re-run the model when your traffic doubles — because the axis that dominates your bill at a thousand creates a day is often not the one that dominates at a hundred thousand.

Frequently asked questions

How do code-execution sandbox platforms actually charge in 2026?

Most bill on some combination of the same axes: a compute meter (per-second wall-clock, per-vCPU-second and per-GiB-second, or active-CPU-only), plus network egress, plus durable volume and snapshot storage, sometimes plus a platform or seat minimum. The compute meter is where the headline rate lives, but your effective cost is decided by the modifiers around it — whether idle time is billed, what increment the meter rounds to, whether there's a per-invocation minimum, and which resource tier you're forced into by your heaviest workload. Pricing in this category changes frequently, so verify every vendor's current terms against their own published docs on the day you evaluate and record the date.

Do I pay for sandbox time while my AI agent is waiting on the LLM?

Under a per-second wall-clock model, yes — every second the sandbox exists is billed, including the seconds it spends completely idle while a model streams tokens. This is the largest hidden cost in agent workloads, because an agent sandbox is typically idle for the large majority of its lifetime — measure your own ratio of active CPU time to wall clock, since it's the number that decides which billing model suits you. Three structural fixes exist: an active-CPU-only billing model where the vendor absorbs idle, scale-to-zero or hibernation that suspends the sandbox and stops the meter, or simply killing the sandbox and creating a fresh one per turn — which is only rational when create latency is low enough that recreation is cheaper than waiting. Ask any vendor explicitly what idle costs, since it's rarely spelled out on the pricing page.

Why does slow cold start make a sandbox platform more expensive?

Because slow provisioning forces you to build a warm pool, and a warm pool is billed compute doing nothing. If create takes several seconds, you can't create per request without users feeling it, so you keep sandboxes pre-started — sized for peak concurrency, which means you pay for peak-shaped capacity against trough-shaped load, plus the engineering time to build and tune the pool manager. Fast create removes the whole category: when a create returns in under 200 milliseconds, ephemeral sandboxes become practical and idle cost approaches zero because there is no idle. PandaStack restores a baked Firecracker snapshot on every create (about 49 ms for the restore step, 179 ms p50 end to end, roughly 203 ms p99) with no warm pool at all. When comparing vendors, add your projected warm-pool cost to the quote of any platform whose create latency would force you to run one.

How do I estimate my monthly sandbox bill before committing?

Model four variables you can measure in an afternoon: creates per day, mean sandbox lifetime from create to kill, the resource tier you reserve, and your active-CPU fraction. Then apply the vendor's modifiers in order — the idle rule first (does lifetime or active time get billed?), then any per-invocation minimum, then the rounding increment — multiply by the rate for your vCPU and memory size, and add egress, storage, and any platform fee. The absolute total matters less than two sensitivity checks: re-run the model with idle billing toggled off, and re-run it with the rounding increment set to sixty seconds. Whichever delta is larger is the axis that actually decides your bill and the one to negotiate on. Finally, validate the model against a real invoice from a one-week trial before you commit to anything.

What questions should I ask a sandbox vendor about pricing?

Four. First: am I billed while idle, and what counts as idle — specifically, what do thirty seconds of zero CPU with memory still resident cost me? Second: what's the rounding increment, the minimum billable duration, and does the meter start at my create call or when the sandbox is ready (if it starts at the call, their provisioning latency is on your invoice)? Third: what are the hard caps on my plan — concurrent sandboxes, creates per minute, max lifetime, max memory — what happens at the ceiling, and where does the next tier start? Fourth: what's billed outside compute — egress, durable volumes, snapshot and image storage, platform minimums — and are snapshots garbage-collected when their sandbox is deleted? Get the answers in writing and date them, because terms in this category move.

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.