---
description: Understand how a Container is deployed, started, routed, and shut down across Cloudflare's network.
title: Lifecycle of a Container
image: https://developers.cloudflare.com/containers/concepts/architecture/og.png?v=9fb00333f140e961
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/containers/llms.txt  
> Use this file to discover all available pages before exploring further.

# Lifecycle of a Container

Last updated Sep 30, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/containers/concepts/architecture/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

## Deployment

How images and running Container instances update depends on the [scheduling policy](https://developers.cloudflare.com/containers/configuration/scheduling-policy/) for the application.

With the `durable_object` policy, Wrangler prepares the named images for the application. Durable Object code can access their immutable references and selects an image and instance size when it calls `ctx.container.start()`. When an image reference changes, the Durable Object code decides whether to stop the running Container and start it with the new image or let it continue with the previous image. This application-controlled restart is how you roll out image changes with the `durable_object` policy. These instances do not participate in application-wide image rollouts.

With the `default` policy, Wrangler uploads or resolves the application image. Cloudflare distributes that image across its network and prepares capacity for new instances. Changes to the image or instance type use a [rollout](https://developers.cloudflare.com/containers/configuration/rollouts/).

Worker code goes live on deploy before any application-wide Container rollout finishes. Refer to [Deploy Containers](https://developers.cloudflare.com/containers/guides/deploy/).

## Container instance lifecycle

```
flowchart LR
    accTitle: Container instance lifecycle
    accDescr: A Worker accesses a container through its Durable Object. The container moves from stopped to starting, running but not ready, ready for traffic, stopping, and stopped.

    Worker["Worker"] -->|Durable Object binding| DurableObject["Durable Object"]
    DurableObject -->|<code>ctx.container</code>| Container

    subgraph Container["Container instance"]
        direction TD
        Stopped["Stopped"]
        Starting["Starting<br/><code>start()</code> called"]
        Running["Running<br/>Not ready"]
        Ready["Ready<br/>Accepting traffic"]
        Stopping["Stopping<br/>Stop requested"]
        StoppedAgain["Stopped"]

        Stopped --> Starting --> Running --> Ready --> Stopping --> StoppedAgain
    end

```

A Container can only be accessed through its [Durable Object](https://developers.cloudflare.com/durable-objects/). A Worker sends a request to the Durable Object, which accesses the Container through `ctx.container`.

An inactivity timeout, `signal()`, `destroy()`, a rollout, or a process exit can stop the instance. If startup fails or the process exits early, the instance returns to the stopped state.

The `ctx.container.running` property becomes `true` before the process is ready to accept traffic. Check port readiness before you send the first request.

For new applications, manage this lifecycle through the [Durable Object Container API](https://developers.cloudflare.com/containers/api/durable-object-container/). It lets the Durable Object coordinate container compute with persistent state and alarms. Existing applications may use the [`Container` class](https://developers.cloudflare.com/containers/api/container-class/). To compare both APIs, refer to [Containers APIs](https://developers.cloudflare.com/containers/api/).

## Lifecycle of a request

### Client to Worker

Recall that Containers are backed by [Durable Objects](https://developers.cloudflare.com/durable-objects/) and [Workers](https://developers.cloudflare.com/workers/). Requests are first routed through a Worker, which 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](https://developers.cloudflare.com/workers/configuration/placement/) is on, or if the nearest location is under heavy load.

Because all Container requests are passed through a Worker, end-users cannot make non-HTTP 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 ↗︎](https://forms.gle/AGSq54VvUje6kmKu8).

### Worker to Durable Object

From the Worker, a request passes through a Durable Object instance. You can extend `DurableObject` and use `ctx.container` directly, or extend the [`Container` class](https://developers.cloudflare.com/containers/api/container-class/). Each Durable Object instance is a globally routable isolate that can execute code and store state. This allows developers to address and route to specific container instances, run code when a container exits, and store persistent state associated with each instance.

### Starting a Container

When a Durable Object requests a new Container instance, Cloudflare selects eligible capacity with the required image available. The `durable_object` policy uses the `image` and `instance` options supplied to `ctx.container.start()`. The `default` policy uses the application image and instance type from Wrangler configuration.

Note

Durable Objects and their associated Container instances are not guaranteed to run in the same location.

Container placement is optimized for request routing and startup speed, so a Container may start in a different location than its Durable Object.

Starting additional Container instances can use other locations where the image is available. Cloudflare prepares additional capacity as demand grows. Because prepared capacity is finite, some Container instances may start in locations farther from the end user. You are only charged for actively running instances, not for prepared images that are not running.

#### Cold starts

A cold start is when a container instance is started from a completely stopped state. If you call `env.MY_CONTAINER.get(id)` with a completely novel ID and launch this instance for the first time, it will result in a cold start. This will start the container image from its entrypoint for the first time. Depending on what this entrypoint does, it will take a variable amount of time to start.

Container cold starts can often be in the 1-3 second range, but this is dependent on image size and code execution time, among other factors.

### Requests to running Containers

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

However, once that container instance stops and restarts, future requests could be routed to a *different* location. This location will again be the nearest location to the originating request with a pre-fetched image.

### Container runtime

Each container instance runs in a Firecracker microVM with its own kernel and network. No other workload on the Cloudflare network shares that kernel. Your image runs as a Linux container inside the VM.

Containers should be built for the `linux/amd64` architecture, and should stay within [size limits](https://developers.cloudflare.com/containers/platform/limits/).

[Logging](https://developers.cloudflare.com/containers/faq/#how-do-container-logs-work), metrics collection, and [networking](https://developers.cloudflare.com/containers/faq/#how-do-i-allow-or-disallow-egress-from-my-container) are automatically set up on each container, as configured by the developer.

### Container shutdown

With the Durable Object Container API, call [`setInactivityTimeout()`](https://developers.cloudflare.com/containers/api/durable-object-container/#setinactivitytimeout) to let the runtime stop the container after the Durable Object becomes inactive. The Durable Object becomes inactive when it stops receiving requests. The timeout can keep the container available while the Durable Object sleeps. You can also stop a container with [`signal()`](https://developers.cloudflare.com/containers/api/durable-object-container/#signal) or [`destroy()`](https://developers.cloudflare.com/containers/api/durable-object-container/#destroy).

The `Container` class sets [`sleepAfter`](https://developers.cloudflare.com/containers/api/container-class/#sleepafter) to 10 minutes by default. Its [`onActivityExpired()`](https://developers.cloudflare.com/containers/api/container-class/#onactivityexpired) implementation calls [`stop()`](https://developers.cloudflare.com/containers/api/container-class/#stop). You can change the duration or override the hook.

When the platform is about to stop a container instance, it:

1. Sends `SIGTERM` to the main process in the container.
2. Waits up to 15 minutes for that process to exit.
3. Sends `SIGKILL` if the process is still running.

Handle `SIGTERM` in your image if you need cleanup before exit. The same sequence runs when a [rollout](https://developers.cloudflare.com/containers/configuration/rollouts/) replaces a container instance with a new image.

### Lifecycle events

The Durable Object Container API provides [`monitor()`](https://developers.cloudflare.com/containers/api/durable-object-container/#monitor). Its promise resolves when the container exits and rejects when the container errors.

The [`Container` class](https://developers.cloudflare.com/containers/api/container-class/) adds hooks that run Worker code when the container changes state:

- [`onStart()`](https://developers.cloudflare.com/containers/api/container-class/#onstart) — Runs after the container has started.
- [`onStop()`](https://developers.cloudflare.com/containers/api/container-class/#onstop) — Runs after the container process exits. Receives the exit code and reason for the stop.
- [`onActivityExpired()`](https://developers.cloudflare.com/containers/api/container-class/#onactivityexpired) — Runs when the [`sleepAfter`](https://developers.cloudflare.com/containers/api/container-class/#sleepafter) timer expires with no incoming requests. The default implementation calls `stop()` to shut down the container. You can use this to only stop the container on certain conditions.
- [`onError()`](https://developers.cloudflare.com/containers/api/container-class/#onerror) — Runs when container startup or port checking fails.

Refer to the [status hooks example](https://developers.cloudflare.com/containers/examples/status-hooks/) for a full implementation.

#### Use snapshots

All disk is ephemeral by default. When a Container instance goes to sleep, the next time it starts, it uses a fresh disk from the container image.

If you need point-in-time filesystem state, Container applications that use the [`durable_object` scheduling policy](https://developers.cloudflare.com/containers/configuration/scheduling-policy/#use-the-durable-object-scheduling-policy) can create and restore a snapshot. Snapshots are immutable, so later file changes require a new snapshot. For more information, refer to [Snapshots](https://developers.cloudflare.com/containers/guides/snapshots/).

You can also use [FUSE](https://developers.cloudflare.com/containers/examples/r2-fuse-mount/) to persist disk to R2 or other object storage backends. Though you should not expect native SSD-like performance while using FUSE.

## An example request

- A developer deploys a Container. Cloudflare automatically readies instances across its Network.
- A request is made from a client in Bariloche, Argentina. It reaches the Worker in a nearby Cloudflare location in Neuquen, Argentina.
- This Worker request calls `getContainer(env.MY_CONTAINER, "session-1337")`. Under the hood, this brings up a Durable Object, which then calls `this.ctx.container.start`.
- This requests the nearest free Container instance. Cloudflare recognizes that an instance is free in Buenos Aires, Argentina, and starts it there.
- A different user needs to route to the same container. This user's request reaches the Worker running in Cloudflare's location in San Diego, US.
- The Worker again calls `getContainer(env.MY_CONTAINER, "session-1337")`.
- If the initial container instance is still running, the request is routed to the original location in Buenos Aires. If the initial container has gone to sleep, Cloudflare will once again try to find the nearest "free" instance of the Container, likely one in North America, and start an instance there.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/containers/concepts/architecture/#page","headline":"Lifecycle of a Container","description":"Understand how a Container is deployed, started, routed, and shut down across Cloudflare's network.","url":"https://developers.cloudflare.com/containers/concepts/architecture/","inLanguage":"en","image":"https://developers.cloudflare.com/containers/concepts/architecture/og.png?v=9fb00333f140e961","dateModified":"2026-09-30","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
