Environments

An environment is an isolated instance of your project with its own containers, domains, database, and configuration. Every project has at least one environment (production). Additional environments let you test changes safely before they affect real users. There is no default cap on the number of environments per project — limits are opt-in and configured by an admin when needed.


What is an environment

An environment is the combination of:

  • Running containers — One or more Docker containers serving your application
  • A domain — An auto-assigned subdomain plus optional custom domains
  • Environment variables — Configuration values specific to this environment
  • A deployment config — CPU limits, memory limits, replica count, and exposed port
  • Its own database — When linked to a managed service, each environment gets an isolated database (e.g. my_app_production vs my_app_staging)
  • Security configuration — Attack mode and other security settings can be configured per environment, overriding the project-level default

Environments within the same project share the Git repository, the project settings, and the linked managed services. But each environment runs its own containers with its own configuration.


Environment types

TypeCreated byTypical use
ProductionAutomatically when the project is createdThe live application. Pushes to the main branch deploy here.
StagingManually by the userA pre-production environment for testing. Can track a staging or develop branch.
PreviewAutomatically when a branch is pushed (if preview environments are enabled)Temporary environments for code review. One per feature branch.

Production environment

Every project has exactly one production environment. It is created when the project is created and cannot be deleted. The production environment:

  • Receives deployments when the project's main branch (usually main) is pushed
  • Is the default target for custom domains
  • Has its own deployment config that can differ from other environments

Preview environments

When enable_preview_environments is turned on for a project, pushing to any non-main branch automatically creates a preview environment. The environment is named after the branch.

Preview environments:

  • Are marked with is_preview: true
  • Get a URL in the format {project}-{branch-slug}.{preview-domain}
  • Respect the include_in_preview flag on environment variables
  • Get their own isolated database within linked services
  • Are soft-deleted when removed (and restored if the same branch is pushed again)

How isolation works

Each environment is fully isolated from the others:

Containers

Each environment runs its own set of Docker containers. A production deployment and a staging deployment are separate containers running different versions of the code (or the same code with different configuration).

Databases

When a managed PostgreSQL service is linked to a project, each environment gets a dedicated database:

postgres-my-db
  ├── my_app_production     (production environment)
  ├── my_app_staging         (staging environment)
  └── my_app_feature_login   (preview environment)

For Redis, each environment gets a dedicated database number (0-15). For S3/RustFS, each environment gets a dedicated bucket.

Environment variables

Variables can be scoped to specific environments. A variable set only for production is not visible in staging or previews. Auto-injected service variables (like POSTGRES_URL) use the environment-specific database name.

Domains

Each environment has its own auto-assigned subdomain. Custom domains are added per environment. SSL certificates are provisioned independently.


Environment configuration

Each environment has its own deployment configuration:

  • Name
    CPU Request / Limit
    Description

    Minimum and maximum CPU allocation in millicores. Environment-level settings override the project defaults.

  • Name
    Memory Request / Limit
    Description

    Minimum and maximum memory in MB.

  • Name
    Replicas
    Description

    Number of container instances. Default: 1. Production might use 3 replicas while staging uses 1.

  • Name
    Exposed Port
    Description

    The port your application listens on. Overrides the project-level setting for this environment.

  • Name
    Branch
    Description

    The Git branch this environment tracks. Pushes to this branch trigger a deployment to this environment.

  • Name
    Attack Mode
    Description

    The attack mode level for this environment. When set, it overrides the project-level default. Use this to apply stricter protection on production while keeping a more permissive setting on preview environments. See Attack mode — per-environment override for details.

Settings are updated at PUT /projects/{id}/environments/{id}/settings or via the dashboard under the environment's Settings tab.


Branch-to-environment mapping

Temps maps Git branches to environments:

BranchEnvironmentCondition
Project's main branch (e.g. main)ProductionAlways
Any other branchPreview environment with matching nameOnly if enable_preview_environments is on
A branch tracked by a manually created environmentThat specific environmentBranch set in environment config

Each branch can only be tracked by one active environment per project. If you create a staging environment tracking the develop branch, pushes to develop deploy to staging (not production).


Lifecycle

Creation

  • Production: Created automatically when the project is created
  • Manual environments: Created via the dashboard or API
  • Preview environments: Created automatically on first push to a non-main branch

There is no default cap on the number of environments per project. You can create as many staging, QA, or preview environments as your workflow requires without hitting a hard limit.

If you need to restrict how many environments a project can have — for example to control resource usage — an admin can configure an optional environment count limit under the project's Settings page. This limit is disabled by default and only takes effect when explicitly set.

Soft deletion

When you delete an environment:

  1. Running containers are stopped and removed
  2. The environment record is marked with a deleted_at timestamp (soft delete)
  3. Data in linked services (database, cache) is not deleted
  4. If the same branch is pushed again, the environment is restored

Protection

The production environment cannot be deleted. This is enforced at the system level regardless of user role or permissions. Other environments can be deleted by users with the appropriate role.

Cleanup

Preview environments accumulate as branches are created. Clean them up manually from the Environments page or by using the Teardown action on individual deployments to free containers while keeping the environment record.


On-demand environments

On-demand mode (also called scale-to-zero) is an optional mode for non-production environments that have infrequent traffic. When enabled, the environment's containers are stopped after a configurable idle period and restarted automatically the first time a new request arrives.

Operational states

An on-demand environment moves through the following states:

StateMeaning
RunningContainers are up and serving traffic normally
SleepingContainers have been stopped due to inactivity; no compute is consumed
WakingA request was received while sleeping; containers are starting

Wake sequence

When a request arrives for a sleeping environment:

  1. Wake trigger — The proxy detects that the environment is sleeping and issues an in-process wake command.
  2. Route reload — The platform performs an in-process ForceRouteReload so the proxy immediately becomes aware of the new container address as soon as it is assigned.
  3. TCP readiness probe — The platform polls the container's exposed port until it accepts connections, confirming the application is ready.
  4. Request forwarded — Once the TCP probe succeeds, the held request is forwarded to the container and a response is returned to the caller.

The first request is held — not dropped — for the duration of the wake sequence. Callers do not need to implement retry logic for waking; a single request is sufficient.

Error handling

503 responses emitted during the wake sequence do not expose internal detail about the environment's sleep state or the wake progress. If the container fails to become healthy within the wake timeout, the caller receives a generic 503 response.

When to use on-demand mode

On-demand mode is suited for:

  • Preview environments that are only accessed during active code review
  • Staging environments with irregular or scheduled usage
  • Internal tools and admin panels with low request frequency

On-demand mode is not recommended for production environments, where cold-start latency is unacceptable and containers must be ready at all times.

Was this page helpful?