Skip to content
Cloudflare Docs

Architecture

This page describes the architecture of Cloudflare Containers.

How and where containers run

After you deploy a Worker that uses a Container, your image is uploaded to Cloudflare's Registry and distributed globally to Cloudflare's Network. Cloudflare will pre-schedule instances and pre-fetch images across the globe to ensure quick start times when scaling up the number of concurrent container instances. This allows you to call env.YOUR_CONTAINER.get(id) and get a new instance quickly without worrying about the underlying scaling.

When a request is made to start a new container instance, the nearest location with a pre-fetched image is selected. Subsequent requests to the same instance, regardless of where they originate, will be routed to this location as long as the instance stays alive.

Starting additional container instances will use other locations with pre-fetched images, and Cloudflare will automatically begin prepping additional machines behind the scenes for additional scaling and quick cold starts. Because there are a finite number pre-warmed locations, some container instances may be started in locations that are farther away from the end-user. This is done to ensure that the container instance starts quickly. You are only charged for actively running instances and not for any unused pre-warmed images.

Each container instance runs inside its own VM, which provides strong isolation from other workloads running on Cloudflare's network. Containers should be built for the linux/amd64 architecture, and should stay within size limits. Logging, metrics collection, and networking are automatically set up on each container.

Life of a Container Request

When a request is made to any Worker, including one with an associated Container, it is generally handled by a datacenter in a location with the best latency between itself and the requesting user. A different datacenter may be selected to optimize overall latency, if Smart Placement is on, or if the nearest location is under heavy load.

When a request is made to a Container instance, it is sent through a Durable Object, which can be defined by either using a DurableObject or the Container class, which extends Durable Objects with Container-specific APIs and helpers. We recommend using Container, see the Container class documentation for more details.

Each Durable Object is a globally routable isolate that can execute code and store state. This allows developers to easily address and route to specific container instances (no matter where they are placed), define and run hooks on container status changes, execute recurring checks on the instance, and store persistent state associated with each instance.

As mentioned above, when a container instance starts, it is launched in the nearest pre-warmed location. This means that code in a container is usually executed in a different location than the one handling the Workers request.

Because all Container requests are passed through a Worker, end-users cannot make TCP or UDP requests to a Container instance. If you have a use case that requires inbound TCP or UDP from an end-user, please let us know.