all posts

The Best Batch Compute Platforms for Bursty Jobs in 2026

Ajay Kumar··11 min read

Batch compute is the workload that never gets a conference talk and never stops growing. A nightly risk calculation, a corpus of half a million documents to parse, a parameter sweep, a re-encode of every asset after someone changed a codec, a backfill that has to finish before Monday. The jobs are independent, the failure of any one of them is survivable, and the arrival pattern is spiky in a way that makes every fixed-size cluster either too small on Tuesday or embarrassing on the invoice for the rest of the week.

I am Ajay, I build PandaStack. This is a roundup of where to run that work in 2026. I have grouped the options into three shapes rather than ranking them, because they are not competing for the same job: a queue in front of a cluster, a serverless job runner, and a fleet of ephemeral VMs solve genuinely different problems, and knowing which shape you need eliminates most of the list before you compare a single feature.

The seven things I would actually compare

Every platform here can run a container until it exits. That is not the differentiator. These are, in roughly the order they will decide your answer:

  • Start latency per job. The number that decides whether a fan-out of 5,000 forty-second jobs is sensible or absurd. If provisioning costs a minute and the job costs a minute, half your bill is provisioning.
  • Isolation boundary. Are two jobs separated by a namespace on a shared kernel, by a user-space kernel like gVisor, or by a hypervisor? This matters enormously if the jobs run customer code or customer data, and barely at all if every job is your own trusted binary.
  • Maximum job duration. Every platform has a ceiling somewhere: a task timeout, a partition walltime, a TTL, or the point at which a spot instance is reclaimed. Find yours before the job that grows past it does.
  • GPU availability. A hard filter, not a preference. If your batch is inference or training, several options on this list disappear immediately — including mine.
  • State and scratch. Does a job get a scratch disk, a shared parallel filesystem, or nothing but object storage? Anything that reads a 200 GiB dataset per job has a data-movement problem that dwarfs its compute problem.
  • Pricing granularity, and whether idle is billable. Per-second on the task, per-minute on the task, or per-hour on nodes that exist whether or not work arrived. This is where bursty workloads get expensive in ways the sticker rate does not show.
  • Operational burden. Who runs the scheduler, who patches the nodes, who gets paged when the queue stalls. A platform that is cheaper per core-hour and needs a full-time engineer is not cheaper.
I have deliberately not quoted anyone else's prices in this post. Cloud pricing changes, varies by region, and comes with committed-use and spot discounts that make a single figure misleading. I describe the pricing model — per-second versus per-minute, whether the control plane is free, whether you pay for idle nodes — and you can check the current numbers against the vendor's own calculator, which is the only source that will be right next month.

Three shapes, not one ranking

The grouping is more useful than any ordering, so here it is up front. A queue in front of a cluster gives you the richest scheduling — dependencies, priorities, array jobs, fair-share between teams — at the cost of owning a cluster that has to exist before the work arrives. A serverless job runner gives you a per-task billing model and no cluster at all, at the cost of ceilings you cannot raise and an execution environment you do not control. An ephemeral-VM fleet gives you a hard isolation boundary and a per-job machine, at the cost of having to bring your own queue.

Almost every argument I have seen about batch platforms is actually two people who have chosen different shapes and are comparing features across the gap.

Shape one: a queue in front of a cluster

AWS Batch

The default answer inside AWS and, for a large class of workloads, simply the right one. You define a compute environment, Batch scales EC2 or Fargate capacity to match the queue, and you get the scheduling features that make batch batch: job dependencies, array jobs with thousands of indices from a single submission, priority queues, and a first-class relationship with Spot that is the main reason anyone tolerates the configuration surface. GPU job definitions are properly supported, and the ecosystem around it — S3, FSx for Lustre, ECR, CloudWatch — is the deepest of anything here.

The costs are honest ones. Start latency depends entirely on whether capacity is already warm: a job landing on a running instance starts in seconds, and a job that triggers a scale-out waits for an instance to launch and an image to pull. The isolation boundary is whichever one you picked — tasks on EC2 share the instance kernel unless you deliberately run one job per instance, while Fargate puts each task in its own microVM, which is a genuinely different security posture for the same YAML. And the control plane is free, but the capacity is not: a compute environment with a minimum vCPU floor is a bill that arrives whether or not the queue is empty.

Pick this if you are already on AWS, need array jobs or dependencies, need GPUs, and your data is in S3 or on a Lustre mount.

Azure Batch

The same shape with an Azure accent, and unusually good at the thing it was originally built for: pools of VMs running task-parallel work, with an SDK-first model where your client application creates the pool, submits tasks and collects results. It has autoscale formulas, low-priority and spot VM support, and a genuinely strong story for Windows batch workloads, which nothing else on this list can say. Rendering and engineering simulation shops use it heavily and are not wrong to.

Its trade-offs mirror AWS Batch: tasks share a node kernel by default, pool VMs are billed while they exist, and start latency is measured in node-provisioning time when the pool needs to grow. Pick this if you are on Azure, or if a meaningful part of your batch is Windows.

Kubernetes Jobs, Argo Workflows and Volcano

If you already run Kubernetes, the Job and CronJob primitives are sitting there, and for a lot of teams that is the end of the analysis. A Job with a completions count and a parallelism cap is a perfectly serviceable array job. Add Argo Workflows when the batch is really a DAG rather than a bag of independent tasks, and add Volcano or Kueue when you need gang scheduling, queue-level fair share, and the sort of resource-quota arbitration between teams that vanilla Kubernetes does not do. GPU support via device plugins is mature and is why most ML training platforms are built on this stack.

The honest weaknesses are the ones everyone knows and underweights anyway. Pod start on a warm node is seconds and dominated by image pull; pod start that requires the cluster autoscaler to add a node is a minute or more, and bursty workloads hit that path constantly. Nodes cost money while they idle, so a cluster sized for your peak is a cluster you pay for at your trough. And the isolation boundary is a shared kernel — fine for your own code, a real conversation if the jobs process untrusted input, which is why gVisor and Kata exist as bolt-ons.

Pick this if you already have a cluster and a platform team, or if your batch is a dependency graph rather than a fan-out.

HashiCorp Nomad

The underrated option, and the one I would look at hardest if I were running batch on my own hardware. Nomad has a first-class batch scheduler, a genuinely small operational footprint compared to Kubernetes, and a driver model that means the unit of work does not have to be a container — it will happily run a raw binary, a Java jar, or a QEMU image. Its dispatch-job feature covers parameterised fan-out cleanly.

You still own the client fleet, so the idle-cost arithmetic is the same as Kubernetes, and the ecosystem is much smaller: fewer managed offerings, fewer people who have already solved your problem on a forum. Pick it if you want cluster scheduling without the Kubernetes surface area, or if your workloads are not all containers.

Shape two: serverless job runners

Google Cloud Run Jobs and Google Cloud Batch

Google ships two things here and the distinction matters. Cloud Run Jobs runs a container to completion with a task count and a parallelism setting, no cluster, and billing tied to task execution — the closest thing to a genuinely serverless array job on a major cloud. Cloud Batch is the AWS Batch analogue: it provisions Compute Engine VMs, supports GPUs, and is the one to use when the job needs more than a Cloud Run task is allowed to have.

Cloud Run Jobs is the cleanest low-burden option on this list for CPU work that fits inside its ceilings, and its execution environments are sandboxed rather than plain shared-kernel containers, which is a better isolation story than most people assume. Check the current per-task timeout and resource limits before committing, because the ceiling is the whole question with this one. Pick Cloud Run Jobs for medium-length CPU tasks you want to stop thinking about; pick Cloud Batch when you need GPUs or long-running VMs on GCP.

The best developer experience in this entire post, and I would rather say that plainly than pretend otherwise. You decorate a Python function, call a map over an iterable, and Modal fans it out across its own fleet with container start times they have worked extremely hard on. GPUs are first-class, the image build system is fast and declarative, and there is no cluster to think about at all. For a Python-shaped batch — inference over a dataset, embedding a corpus, a scientific sweep — it removes almost all of the infrastructure.

The trade-offs are the ones any opinionated platform has. It is Python-first, so a batch of Go binaries or a legacy C++ toolchain fits less naturally. You are inside their execution model, which is excellent until you need something it does not express. And the billing is per-unit-of-execution on their fleet, which is the right model for bursty work but means the cost picture is theirs, not yours. Pick Modal if your batch is Python and needs GPUs, and you would rather write a decorator than a job definition.

Ray and Dask as a service (Anyscale, Coiled)

A different category that people reach for when their batch is not really a batch. If the work is a dataframe operation over more memory than one machine has, or a reinforcement-learning workload with actors that talk to each other, then a task scheduler is the wrong abstraction and a distributed compute framework is the right one. Ray gives you tasks, actors and a scheduler designed for ML workloads; Dask gives you the same NumPy and pandas APIs at cluster scale; Anyscale and Coiled run the cluster for you and spin it down when idle.

The honest boundary: these are clusters with a lifetime, even when a service manages that lifetime for you. Cluster startup is a real cost paid once per session rather than per task, which is excellent for a long analysis session and poor for a single forty-second job arriving at an unpredictable hour. Pick these when the work is data-parallel with real inter-task communication, not when it is a bag of independent processes.

The contrast case: Slurm and traditional HPC

Slurm deserves its place here precisely because it is not a cloud product. It is the scheduler running most of the world's serious scientific computing, it has three decades of accumulated understanding of what a queue needs, and its feature set makes cloud batch schedulers look thin: backfill scheduling, fair-share accounting across accounts, topology-aware placement, job arrays, reservations, preemption policies with actual nuance.

It also assumes a world that cloud batch does not: a fixed set of nodes you own, a shared parallel filesystem every node mounts, a low-latency interconnect, and a queue where waiting hours for a slot is normal rather than a failure. If your job is tightly coupled MPI across dozens of nodes, this is not merely an option, it is the option — nothing else on this list will give you an InfiniBand fabric and a scheduler that understands node topology. If your job is 5,000 independent Python processes that arrive in a burst at 02:00 and must all be done by 03:00, Slurm's model of queue wait is exactly wrong for you.

Cloud batch platforms optimise for the case where capacity is elastic and wait time is a failure. HPC schedulers optimise for the case where capacity is fixed and wait time is the price of admission. Neither is confused; they are answering different questions.

Shape three: ephemeral-VM fleets, which is where we sit

PandaStack is the third shape: there is no cluster and no warm pool, and every job gets its own Firecracker microVM with its own kernel. Creating a sandbox is a restore of a baked snapshot rather than a boot, which is what makes per-job VMs affordable at all — the p50 for a create is 179ms and the p99 is around 203ms. The first spawn of a template that has never been baked does a genuine cold boot at around three seconds and captures the snapshot on the way through, so you pay a boot once per template rather than once per job.

Three properties are the actual argument for this shape. The isolation boundary is a hypervisor, so a job running a customer's code or parsing a customer's untrusted file is separated from its neighbours by virtualisation rather than by namespaces. There is no idle cost, because there is nothing to idle: a sandbox exists between create and kill, and the meter runs for that interval and no other. And copy-on-write forking means a fan-out can start from a warm parent — do the expensive shared setup once, snapshot, and every child restores into a process that has already loaded your model, your dataset index or your compiled artefacts. A fork-tree call caps at 16 children, so a wider sweep is a loop over batches, and children land in roughly 200 to 500 milliseconds each.

The pricing model is one rate card with two dimensions: $0.054 per vCPU-hour and $0.0162 per GiB-hour, metered per second, identical for sandboxes, apps and managed databases. Egress is not billed. The ceilings that matter for batch are the per-tier TTL and create-rate limits: the free tier caps a sandbox at one hour and 60 creates per hour, Pro at seven days and 600 creates per hour, Team at thirty days and 6,000 creates per hour.

The most important thing to know before choosing us for batch: there is no queue. PandaStack gives you a create-a-VM-in-179ms primitive and a kill primitive. Retries, dependency graphs, array-job semantics, fair-share between teams and dead-lettering are yours to build or to keep in whatever queue you already run. That is a deliberate scope decision, not a roadmap gap, and if you want a scheduler with those features out of the box then AWS Batch, Kubernetes plus Kueue, or Slurm are better answers than we are.

The pattern that works is a queue you already trust — SQS, Redis, a Postgres table with SKIP LOCKED — plus a driver process that turns each message into a sandbox. That is a couple of hundred lines, it is entirely yours, and it means the platform never has an opinion about your retry policy.

import json
from concurrent.futures import ThreadPoolExecutor
from pandastack import Sandbox

# Fan-out driver. The queue is yours -- this loop is the only PandaStack part.
# Pattern: do the expensive shared setup ONCE in a parent, then fork, so each
# child restores into a guest that has already downloaded the model weights
# and warmed its caches instead of repeating that work N times.

SHARDS = [f"s3://corpus/shard-{i:04d}.jsonl" for i in range(64)]

parent = Sandbox.create(
    template="base",
    ttl_seconds=3600,                     # cheap insurance against a wedged parent
    metadata={"kind": "corpus-parse", "role": "parent"},
)
# filesystem.upload() takes a single file, so ship the worker as one tarball.
parent.filesystem.upload("./worker.tar.gz", "/tmp/worker.tar.gz")
parent.exec("mkdir -p /work/worker && tar -xzf /tmp/worker.tar.gz -C /work/worker", check=True)
parent.exec("cd /work/worker && ./setup.sh", timeout_seconds=900, check=True)


def run(child_and_shard):
    child, shard = child_and_shard
    try:
        r = child.exec(f"/work/worker/run.sh {shard}", timeout_seconds=1800)
        if r.exit_code != 0:
            return {"shard": shard, "ok": False, "stderr": r.stderr[-2000:]}
        return json.loads(child.filesystem.read("/work/out/result.json"))
    except Exception as err:                # a lost host is a normal event here
        return {"shard": shard, "ok": False, "error": str(err)}
    finally:
        child.kill()                        # free the RAM before the next batch


results = []
# fork_tree is capped at 16 children per call, so a wide sweep is a loop.
for start in range(0, len(SHARDS), 16):
    batch = SHARDS[start:start + 16]
    children = parent.fork_tree(count=len(batch), metadata={"kind": "corpus-parse"})
    with ThreadPoolExecutor(max_workers=len(batch)) as pool:
        results.extend(pool.map(run, zip(children, batch)))

parent.kill()

failed = [r for r in results if not r.get("ok", True)]
print(f"{len(results) - len(failed)}/{len(results)} shards succeeded")
# Retry policy lives HERE, in your code, next to the queue that owns the work.

Two details in that script are load-bearing. The `kill()` in a `finally` matters because the resource you are contending for is host memory, and a batch that leaks guests fails the next batch rather than itself. And every sandbox carries metadata, which is what makes the operational questions — what is running, whose work is it, what should the reaper clean up — a query rather than an investigation.

Side by side on the criteria

One list per criterion, which is the honest way to do this when the answers are conditional rather than scalar.

Start latency per job:

  • Fastest, and roughly constant — PandaStack, because a create is a snapshot restore rather than a boot and there is no scale-out path to wait on. p50 179ms.
  • Fast when warm, slow when cold — Kubernetes Jobs, Nomad, AWS Batch, Azure Batch, Cloud Batch. Seconds on existing capacity, a node-provisioning wait when the queue outgrows the cluster. This bimodality is the thing that makes bursty batch frustrating on these platforms.
  • Consistently low without a cluster — Modal and Cloud Run Jobs, which have both invested heavily in container start and have no autoscaler for you to wait on.
  • Whatever the queue says — Slurm. If a node is free, immediate. If not, the wait is a scheduling-policy outcome and can be hours.
  • Once per session, not per task — Ray and Dask clusters. You pay startup at cluster creation, then tasks dispatch in milliseconds.

Isolation boundary between two jobs:

  • Hypervisor, per job, by default — PandaStack, and AWS Batch when you run it on Fargate.
  • Sandboxed runtime — Cloud Run Jobs, whose execution environments are not plain shared-kernel containers. Modal runs its own sandboxed fleet; check their current security documentation for the specifics rather than taking my word for the mechanism.
  • Shared kernel, namespaces and cgroups — Kubernetes Jobs, Nomad with the Docker driver, AWS Batch on EC2, Azure Batch. Perfectly fine for your own trusted code, a real question for untrusted input.
  • Shared kernel, shared multi-user node — Slurm in its traditional configuration, where isolation is a uid and a cgroup and the security model assumes an authenticated institutional user.

GPUs — the filter that decides fastest:

  • Yes, first-class — AWS Batch, Azure Batch, Cloud Batch, Kubernetes, Nomad, Slurm, Modal, Ray.
  • No, and no passthrough — PandaStack. Sandboxes are CPU-only. If your batch is GPU-bound end to end, stop reading about us and pick one of the above; a common shape is CPU fan-out here plus separate GPU infrastructure for the handful of steps that need it.

Do you pay for idle capacity:

  • No — PandaStack (a sandbox exists or it does not), Cloud Run Jobs and Modal (billed against execution), and AWS Batch or Cloud Batch configured with a zero minimum so the compute environment scales to nothing between bursts.
  • Yes, structurally — Kubernetes, Nomad, Azure Batch pools and Slurm, all of which have nodes that exist before the work arrives. Autoscalers reduce this; they do not remove it, and aggressive scale-down trades idle cost for start latency.
  • Somewhere in between — Ray and Dask services, which idle-timeout the cluster. The knob is how long you are willing to wait for the next cluster.

State, scratch and data movement:

  • Parallel filesystem available — Slurm (its native assumption), AWS Batch with FSx for Lustre, Kubernetes with a CSI driver for one. This is decisive if jobs share a large working set.
  • Per-job disk plus object storage — Cloud Run Jobs, Modal, AWS Batch on Fargate, and PandaStack, which gives each guest a private ext4 rootfs and optional durable volumes but no shared parallel filesystem and no MPI interconnect.
  • Whatever you mount — Kubernetes and Nomad, which will attach almost anything and make it your problem to operate.

Operational burden, lowest to highest: Cloud Run Jobs and Modal, then PandaStack (low to run, but you supply the queue), then AWS Batch and Azure Batch and Cloud Batch, then Nomad, then Kubernetes with Argo or Volcano, then self-operated Slurm, which is a job title rather than a config file.

How to choose, in about two minutes

  1. Do the jobs need GPUs? If yes, PandaStack is out. If the jobs are Python, look at Modal first. If they are anything else, or you need Spot economics at scale, look at AWS Batch or Cloud Batch.
  2. Do the jobs talk to each other? If it is tightly coupled MPI across nodes, it is Slurm and it is not close. If it is data-parallel with shuffles, it is Ray or Dask. If they are genuinely independent, keep going.
  3. Do you already run a scheduler? If you have a Kubernetes cluster and a platform team, Jobs plus Kueue or Argo is almost always the cheapest decision by total effort, even when it is not the cheapest by core-hour.
  4. Is the arrival pattern spiky and the jobs short? Then start latency and idle cost dominate everything else. That points at Cloud Run Jobs, Modal, or a per-job VM model like ours, and away from anything that provisions a node per burst.
  5. Do the jobs execute untrusted code or parse untrusted input? Then the isolation boundary is a requirement rather than a preference, and the shortlist is per-job microVMs — us, or AWS Batch on Fargate — or a sandboxed runtime like Cloud Run.
  6. Do you need array jobs, dependencies and fair-share out of the box? Then take a queue-in-front-of-a-cluster platform and accept the idle cost, because rebuilding that scheduling logic yourself is a much larger project than it looks on the whiteboard.

Where PandaStack is the wrong answer, stated plainly

  • GPU workloads. CPU-only, no device passthrough. This is the single most common reason a batch team should not use us.
  • Tightly coupled parallel jobs. No MPI interconnect, no topology-aware placement, no shared parallel filesystem. A job that needs 64 ranks talking over InfiniBand needs an HPC cluster, and Slurm is the mature answer.
  • Scheduling features. No array jobs, no dependency graphs, no fair-share queues, no dead-lettering. We give you a fast create and a kill; the queue is yours.
  • Very large per-job memory. Guest RAM is baked into the snapshot, so memory is a property of the template rather than a parameter of the create request. Different sizes mean different baked templates, and the tier ceilings are real — 4 GiB per sandbox on Free, 16 GiB on Pro, 64 GiB on Team.
  • Very long jobs. The TTL ceiling is per-tier, and more to the point, a twelve-hour job has amortised away the entire benefit of a 179ms create. You are paying for provisioning machinery you no longer need.
  • Petabyte-scale data movement. If every job reads hundreds of gigabytes, your bottleneck is the filesystem and not the compute, and a platform with a Lustre mount will beat a platform with fast VM starts every time.

The summary

Most batch platform choices are made on the wrong axis — a comparison of scheduling features between two products that were never going to be the answer anyway. The two questions that eliminate most of the field are whether you need GPUs and whether your arrival pattern justifies a cluster that exists when no work does. Answer those honestly and you are usually down to two candidates before you read a single feature matrix.

If you are on a hyperscaler with GPU-bound work and a queue that needs real scheduling semantics, take AWS Batch or Cloud Batch and do not overthink it. If your batch is Python and you want the infrastructure to disappear, Modal is genuinely excellent at that and I would not pretend otherwise. If the work is tightly coupled science, it is Slurm. The case for per-job microVMs is narrower and specific: bursty arrivals of short-to-medium CPU jobs, a hard isolation requirement because the work is somebody else's code, and an aversion to paying for a cluster that spends most of the week doing nothing. That is our lane, and being clear about where it ends is more useful to you than a longer feature list.

Frequently asked questions

What is the difference between AWS Batch and Kubernetes Jobs for batch workloads?

They occupy the same shape — a queue in front of a cluster — but differ in who owns the scaling and how rich the scheduling is. AWS Batch manages the compute environment for you: it launches and terminates EC2 or Fargate capacity in response to queue depth, and it ships batch-specific semantics like array jobs, job dependencies and priority queues that Kubernetes does not have natively. Kubernetes Jobs give you a completions count and a parallelism cap, which covers simple fan-out, but dependency graphs need Argo Workflows and queue-level fair share needs Kueue or Volcano bolted on. The practical decision usually comes down to what you already run: if you have a cluster and a platform team, the marginal cost of running batch on it is small even though the feature set is thinner. If you do not, AWS Batch saves you from operating a cluster whose only job is to be there when the queue fills.

How fast does a batch job actually start on each of these platforms?

It depends almost entirely on whether capacity already exists, and that is the point. On Kubernetes, Nomad, AWS Batch or Azure Batch, a job landing on a node that is already running starts in seconds and is usually dominated by the container image pull; a job that triggers a scale-out waits for a VM to launch, boot and pull the image, which is typically a minute or more. Serverless job runners like Cloud Run Jobs and Modal remove the scale-out path entirely and start consistently fast. Slurm's answer is scheduling policy rather than mechanics: immediate if a node is free, hours if the queue is deep. PandaStack sits at the fast and constant end because a create is a restore of a baked Firecracker snapshot rather than a boot, at a p50 of 179ms and a p99 of around 203ms, with no warm pool and therefore no cold path to fall off.

Can I run batch jobs without paying for an idle cluster?

Yes, and it is the main reason to prefer a serverless or ephemeral-VM model for bursty work. Cloud Run Jobs and Modal bill against task execution rather than nodes. AWS Batch and Google Cloud Batch can be configured with a zero minimum so the compute environment scales down to nothing between bursts, though you trade that against the scale-out latency of the next burst. PandaStack has no cluster to idle at all: a sandbox exists between create and kill and the meter runs for exactly that interval, at $0.054 per vCPU-hour and $0.0162 per GiB-hour, metered per second, with egress not billed. Kubernetes, Nomad, Azure Batch pools and Slurm all have nodes that exist before the work arrives, and autoscalers reduce that cost without removing it — the honest framing is that you are choosing where on the idle-cost versus start-latency curve you want to sit.

When should I use a microVM per job instead of a container per job?

When the isolation boundary is a requirement rather than a preference. A container separates jobs with namespaces, cgroups and seccomp on a kernel they all share, which is entirely reasonable when every job runs your own trusted code. It becomes a real question when jobs execute customer-supplied code, parse untrusted files, or run generated SQL, because the shared syscall surface is where every container escape of the last decade has lived. A microVM gives each job its own kernel behind a hypervisor, which is a boundary you can describe in a sentence to whoever is going to ask. The historical objection was that VMs are too slow to provision per job, and snapshot-restore is what removed it — restoring a baked snapshot is a fundamentally different operation from booting, which is how per-job VMs reach sub-second creates.

Does PandaStack support GPU batch jobs?

No. Sandboxes are CPU-only and there is no GPU passthrough, so any batch that depends on GPU acceleration — training, most modern inference, GPU-accelerated simulation — has to run elsewhere. This is a genuine limitation rather than something to design around, and it is the first filter I would apply if I were choosing a platform. The options that do this well are AWS Batch, Google Cloud Batch, Azure Batch, Kubernetes with device plugins, Slurm, and Modal if the work is Python. A shape that works in practice is a CPU fan-out on microVMs for the preprocessing, parsing and post-processing stages, with GPU infrastructure handling only the steps that actually need a GPU — those stages are usually the majority of the wall-clock time and the minority of the GPU bill.

Do I still need a job queue if every job gets its own VM?

Yes, and PandaStack deliberately does not provide one. What you get is a create primitive fast enough that a VM per job is sensible, plus a kill primitive; retries, dependency ordering, array-job semantics, priorities and dead-lettering are yours. In practice that means a queue you already trust — SQS, a Redis list, a Postgres table with SELECT FOR UPDATE SKIP LOCKED — and a driver process that turns each message into a sandbox, runs the work, reads a result file back, and kills the guest in a finally block. It is a couple of hundred lines and it keeps your retry policy next to the queue that owns the work. If you would rather that logic came in the box, a queue-in-front-of-a-cluster platform like AWS Batch or Kubernetes with Kueue is a better fit and I would say so before you built anything.

Keep reading

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.