Containers hit public beta on Cloudflare’s developer platform
Cloudflare Containers are now available in public beta for all users on paid plans. The new service lets developers run containerized workloads alongside Workers, covering use cases like media and data processing at the edge, backend services in any language, and CLI tools in batch jobs.
Containers are integrated with the existing Workers developer experience:
- Simple workflow: Define a Container in configuration and run
wrangler deploy, just as with a Worker. - Global by default: Deploy to Region:Earth with no multi-region configuration.
- Right tool for the job: Route between lightweight Workers and more powerful Containers as needed.
- Programmable: Worker code controls container instance lifecycle, spinning instances up on demand instead of chaining API calls or managing Kubernetes operators.
Running sandboxed code with Containers
A representative use case is code sandboxing, where each user gets an isolated, globally distributed container that starts quickly. The Worker declares basic configuration — default port, sleep timeout, and image — in wrangler.jsonc using the Container class, then routes to it.
For each unique ID passed to the Container’s binding, Cloudflare provisions a new instance at the best available location where a ready-to-go container has been pre-provisioned. Initial container start takes a few seconds; routing, provisioning, and scaling are handled automatically. A Worker can route requests to a unique container instance for each sandbox ID at a path like /sandbox/ID, with standard Worker JavaScript handling everything else.
export class MyContainer extends Container {
defaultPort = 8080; // The default port for the container to listen on
sleepAfter = '5m'; // Sleep the container if no requests are made in this timeframe
}
export default {
async fetch(request, env) {
const pathname = new URL(request.url).pathname;
// handle request with an on-demand container instance
if (pathname.startsWith('/sandbox/')) {
const sessionId = pathname.split("/")[2]
const containerInstance = getContainer(env.CONTAINER_SANDBOX, sessionId)
return await containerInstance.fetch(request);
}
// handle request with my Worker code otherwise
return myWorkerRequestHandler(request);
},
};
Local development with wrangler
Configuration specifies either a container image URL or a path to a local Dockerfile. Running wrangler dev builds the image automatically and makes it routable through the local Worker. Pressing “R” in the terminal rebuilds and restarts the Container, allowing concurrent iteration on both Worker and container code.
"containers": [
{
"class_name": "ContainerSandbox",
"image": "./Dockerfile",
"max_instances": 80,
"instance_type": "basic"
}
]
Deploying and monitoring
Running wrangler deploy pushes the image to the account and provisions it across Cloudflare’s network. Image management, distribution, and auth are handled by the platform.
Observability is built in. The dashboard shows status and resource usage per instance, and logs are retained in the Cloudflare UI for seven days or can be pushed to an external sink.


Use cases and platform integration
The beta unlocks workloads that previously couldn’t run on Workers, such as an FFmpeg-based Worker that converts video to GIF, a container running as part of a cron job, a static frontend with a containerized backend, and a Cloudflare Agent running Claude Code in a Container.
Containers integrate with other developer platform services: Durable Objects for state management, Workflows, Queues, Agents for complex behavior, and R2 for data or media storage.
Pricing and included usage
At launch, instance sizes are limited, with plans to add larger options over time:
Name | Memory | CPU | Disk |
|---|---|---|---|
dev | 256 MiB | 1/16 vCPU | 2 GB |
basic | 1 GiB | 1/4 vCPU | 4 GB |
standard | 4 GiB | 1/2 vCPU | 4 GB |
Charges start when a request is sent to a container or when it is manually started, and stop after the instance sleeps (automatically after a timeout). This supports scaling to zero and high utilization under bursty traffic.
Active containers are billed per 10ms of runtime at these rates, with monthly amounts included in Workers Standard:
- Memory: $0.0000025 per GiB-second, with 25 GiB-hours included
- CPU: $0.000020 per vCPU-second, with 375 vCPU-minutes included
- Disk: $0.00000007 per GB-second, with 200 GB-hours included
Egress is priced with monthly included amounts under Workers Standard:
- North America and Europe: $0.025 per GB with 1 TB included
- Australia, New Zealand, Taiwan, and Korea: $0.050 per GB with 500 GB included
- Everywhere else: $0.040 per GB with 500 GB included
Roadmap
Current limits cap concurrent instances at 40 total GiB of memory and 40 total vCPU. Cloudflare plans to raise these limits over the coming months; select customers are already running thousands of concurrent containers.
Upcoming features include:
- Global autoscaling and latency-aware routing: Route to one of many stateless instances and autoscale live instances with a single line of code, routing to the nearest ready instance.
- More Worker-Container communication: An
execcommand to run shell commands in an instance, and handlers for HTTP requests from the container back to Workers. - Further developer platform integrations: First-party APIs for mounting R2 buckets, reaching Hyperdrive, and accessing KV.
class MyBackend extends Container {
defaultPort = 8080;
autoscale = true; // global autoscaling on - new instances spin up when memory or CPU utilization is high
}
// routes requests to the nearest ready container and load balance globally
async fetch(request, env) {
return getContainer(env.MY_BACKEND).fetch(request);
}
class MyContainer extends Container {
// sets up container-to-worker communication with handlers
handlers = {
"example.cf": "handleRequestFromContainer"
};
handleRequestFromContainer(req) {
return new Response("You are responding from Workers to a Container request to a specific hostname")
}
// use exec to run commands in your container instance
async cloneRepo(repoUrl) {
let command = this.exec(`git clone ${repoUrl}`)
await command.print()
}
}
To try Containers today, deploy the template with npm create cloudflare@latest -- --template=cloudflare/templates/containers-template.



