Skip to main content
Every app runs as a container. You do not choose a machine type, write a Dockerfile, or configure a runtime.

Container resources

Each app runs with: These are fixed today and not configurable from the dashboard.

Scale to zero

An app with no traffic is scaled down to zero instances. It costs nothing while idle.
The trade-off is cold starts. The first request after an idle period has to start a container before it can be served, which typically adds a second or two. Subsequent requests hit the warm instance.

Single instance

Each app runs on at most one instance. There is no horizontal scaling, no configurable instance count, and no load balancing across replicas.This has consequences worth knowing:
  • Concurrent requests are handled by one container. A CPU-bound app under load will queue.
  • In-memory state is not shared across instances, because there is only one, which makes in-memory caching and sessions work, but they are lost on every restart and redeploy.
  • Canary and percentage-based rollouts are not possible, since they require two versions serving at once.
If your app needs to serve real concurrent traffic, this is the limit to plan around.

Region

Apps run in a single region, chosen to sit close to the database. Region selection is not exposed.

Builds

Your container is built from source on every deploy.
  • Buildpacks detect your runtime and produce an image with no Dockerfile required.
  • Your own Dockerfile, when one sits at the root of the directory being built, is used instead. A Dockerfile nested in a subdirectory is not: the build runs at the root and would not find it.
  • Static sites skip the buildpack lifecycle entirely and are layered onto a minimal server image, roughly seventy seconds instead of three minutes.
Build logs are captured and shown in the dashboard, including when a build fails.

Deployments and rollback

Release history, and rolling back to a previous image.