Back to Dispatch
Containers By Elias Makinen 6 min read

Getting Containers Under 50ms

The techniques we use at the infrastructure level to hit sub-50ms cold starts consistently across all 12 of our PoP regions.

Getting Containers Under 50ms

At Symbiosis, 50ms is the cold-start ceiling we use for containers at the edge, not a round number chosen after the fact. A 100ms or 200ms pause is noticeable in a request path meant to feel local, while 50ms leaves room for routing, application work, and the response travelling back to the caller. In early-access pilots, we measured a 14ms average cold start. The work now is making sub-50ms behavior consistent across all 12 PoPs, rather than relying on a favorable average.

This article is about the infrastructure techniques behind that target. A container cold start is a sequence of operations: scheduling, image availability, filesystem setup, process creation, network initialization, and application readiness. Improving only one step leaves the others exposed. Our approach is to remove unnecessary work from the critical path and make the remaining work predictable.

Start with the image, not the machine

The fastest container is the one that does not need to download or assemble much. Image design affects cold-start time before a workload reaches the runtime.

We separate an image into layers with different rates of change:

runtime base
system dependencies
language and framework dependencies
application code
configuration supplied at start time

Stable material comes first and volatile material comes last. That means a code change does not invalidate a large dependency layer. We also keep build tools out of the runtime image, reducing both its size and the number of files the runtime must prepare.

We refer to images by immutable digests during deployment. Each PoP therefore prepares an exact artifact, rather than resolving a tag that may point to different content. This makes cache coordination and deployment state more predictable.

Make the filesystem available before the request

Image caching helps only when the required layers are already usable. A cache containing compressed data may still require expensive preparation on the request path.

At each PoP, we prepare the layers needed by scheduled workloads and keep their runtime representation ready for container creation. When a new image digest is published, the PoP fetches missing layers, verifies them, and prepares the filesystem before traffic is directed to that revision. The request path then avoids a pull and unpack operation wherever the deployment has been prepared in advance.

Cleanup is part of the latency design. Removing every unused layer immediately saves storage but increases the chance that the next start becomes a network transfer and unpack operation. We keep commonly reused layers available and avoid trying to hold every possible image everywhere.

We are not saying image preparation makes a large, previously unseen artifact free to start. A deployment that introduces new dependencies or a much larger runtime still has work to do. This technique removes repeated work for known workloads; it does not eliminate the cost of introducing new bytes.

Pre-warm the execution path

Container creation has a cost even when the image is local. We address that with pre-warming at the edge PoP level.

For a deployed workload, we maintain ready capacity that has already passed the common setup stages. When a request arrives, the container does not need to begin from an entirely cold host state. The warm path still creates an isolated execution context, but it avoids waiting for every prerequisite at request time.

Pre-warming must follow deployment state. A warm container running the previous revision cannot serve as capacity for the revision receiving traffic. During deployment, the new digest is prepared first, then capacity for that digest is brought into the ready state. Only then is it eligible for requests.

We also distinguish process existence from application readiness. A process can be running while dependencies are still initializing. Our measurement ends when the container is ready for its intended request path, not merely when a process identifier appears.

Pre-warming does not fix slow application initialization. If the workload performs expensive migrations, compiles code at startup, or waits on an external dependency, the platform can prepare the container but cannot make that application work disappear. The technique removes platform setup from the critical path; it does not rewrite the workload.

Keep the scheduler out of the critical path

Placement decisions can consume the same budget as container initialization if they require broad coordination. At the PoP level, we keep enough local information to make ordinary placement decisions without waiting for a distant control-plane operation.

The local path knows which image layers are available, which execution capacity is ready, and which deployment revision is eligible. A request can therefore select prepared capacity instead of first asking the wider system to construct it. Control-plane work remains important for deploying and reconciling state, but it should not be required for every normal start.

This is why the PoP is the useful unit for the design. Stockholm, London, Amsterdam, Frankfurt, Paris, New York, Chicago, Los Angeles, Sao Paulo, Singapore, Tokyo, and Sydney each need a local version of the preparation process. A globally fast control path does not help if the target PoP has not prepared the image.

A synthetic case: Sydney instead of Stockholm

Consider a deployment requested in Sydney while its new image digest is not yet present there. Stockholm may already have the layers because the revision was prepared there first. If Sydney waits for the request before fetching and preparing the image, the cold start includes transfer, verification, filesystem preparation, and process startup. It can miss 50ms even if the application itself starts quickly.

The fix is to make regional preparation part of deployment. When Sydney becomes a target for the revision, its missing layers are fetched and made usable before traffic needs them. If demand is low, we still need a policy for which capacity remains warm and which can be reclaimed. That policy balances storage, idle resources, and startup time.

Measure the path, not only the average

We measure cold start as a sequence rather than a single opaque duration. Image availability, preparation, scheduling, container creation, and application readiness each need to be visible. Otherwise, an improvement in one stage can conceal a regression in another.

The 14ms average from early-access pilots tells us that the design can be fast. It does not mean every image, revision, workload, or future deployment will start in 14ms. Our target is sub-50ms cold starts consistently across all 12 PoPs.

There are cases where 50ms is not achievable: a previously unseen large image, heavy application initialization, or a deployment that has not yet been prepared in the target PoP can exceed the budget. Infrastructure can make container startup predictable and remove avoidable delay. It cannot remove network time required by the application or compensate for work that happens before readiness.