Set Up Preview Deployments

Preview deployments create a temporary environment for every non-production branch, giving you a live URL to review changes before merging. There is no default cap on the number of preview environments — teams with many open branches can push freely without hitting a ceiling.


Enable preview environments

Preview deployments are controlled at the project level.

Enable preview environments

  1. 1

    Open your project in the dashboard.

  2. 2

    Go to Settings > General.

  3. 3

    Find Preview Environments and toggle it on.

  4. 4

    Click Save.

    Checkpoint: After saving, push to any branch other than main and confirm a new preview environment appears under the Environments tab.

  1. Open your project in the dashboard
  2. Go to Settings
  3. Find Preview Environments and toggle it on
  4. Click Save

Once enabled, any push to a branch that is not the project's main branch (usually main or master) will automatically create a preview environment and deploy to it.


Run previews on-demand

Turn on on-demand previews

  1. 1

    Open Settings > General for your project.

  2. 2

    Make sure Enable Preview Environments is already on (the on-demand toggle is disabled until it is).

  3. 3

    Turn on On-Demand Preview Environments.

  4. 4

    Set the Idle timeout (60-86400 seconds, default 300) and Wake timeout (5-120 seconds, default 30) inputs that appear.

    Checkpoint: Create a new preview after enabling this and confirm it scales to zero when idle and wakes on the next request; existing previews are unaffected.

By default, every preview environment runs 24/7 just like production. You can instead have each newly created preview start in on-demand mode, where it scales to zero when idle and wakes on the next request — so a stack of stale feature-branch previews stops consuming resources.

Under Settings > General, below the Enable Preview Environments switch, you'll find:

SettingDefaultRangeWhat it does
On-Demand Preview EnvironmentsOffWhen on, every newly auto-created preview starts in on-demand mode
Idle timeout (seconds)3006086400How long a preview sits idle before it scales to zero
Wake timeout (seconds)305120Maximum time the proxy holds the first request while waiting for the container to become ready; the request receives a 503 if this expires

The on-demand toggle is disabled until preview environments are enabled, and the two timeout inputs only appear once on-demand is turned on. Both inputs are validated client-side against the same ranges the backend enforces.

What happens when a sleeping preview receives its first request

When a sleeping preview receives its first request, Temps does not immediately reject it. The proxy holds the request in place and works through these steps:

  1. Container start is triggered. Temps instructs Docker to start the container for the sleeping environment.
  2. The proxy picks up the new address via an in-process route reload. Once the container is registered, Temps triggers a ForceRouteReload internally rather than waiting for a PostgreSQL notification cycle. This eliminates the delay that previously caused the first request to see a 503 for up to ~10 seconds while the proxy waited for a database notification to propagate.
  3. A TCP readiness probe confirms the container's port is open. Temps does not forward the held request until the container is actually accepting TCP connections on its exposed port.
  4. The held request is forwarded and the container responds normally. From the caller's perspective, the first request simply took longer than usual — there is no error response during the wake window.

If the wake timeout expires before the container passes the TCP probe, the held request receives a clean 503 Service Unavailable response. No internal error detail is exposed to the caller.

A successful first-request wake is transparent: the caller sees a longer initial response time (container cold-start), and all subsequent requests are served at normal latency. Once the container is up, it stays up until it goes idle again.

You can also set this through the project-settings update API. The UpdateProjectSettingsRequest body accepts three optional fields:

curl -X POST "https://your-temps-instance/api/projects/{project_id}/settings" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "preview_envs_on_demand": true,
    "preview_envs_idle_timeout_seconds": 300,
    "preview_envs_wake_timeout_seconds": 30
  }'

If a timeout falls outside its valid range, the request is rejected with a validation error (for example, preview_envs_idle_timeout_seconds 30 is not in valid range (60-86400)).


How preview branches work

When a push arrives on a non-main branch:

Deploy a branch to a preview

  1. 1

    Push to a non-main branch (e.g. feature/login) and Temps checks whether a preview environment already exists for it.

  2. 2

    If none exists, Temps creates one named after the branch (feature/login becomes the feature-login environment).

  3. 3

    Temps builds the application and deploys it to that environment.

  4. 4

    A unique preview URL is generated in the format https://my-app-feature-login.yourdomain.com.

    Checkpoint: Open the Environments tab and confirm the branch's preview shows a deployment and a live URL.

  1. Temps checks if a preview environment already exists for that branch
  2. If not, it creates one — the environment is named after the branch (e.g. feature/login becomes the feature-login environment)
  3. The application is built and deployed to that environment
  4. A unique URL is generated for the preview

If the branch is pushed again, Temps redeploys to the same preview environment rather than creating a new one. If a previously deleted branch is pushed again, Temps restores the soft-deleted environment.

Preview URLs

Preview deployments get URLs in the format:

https://{project-slug}-{environment-slug}.{preview-domain}

For example, if your project is my-app and the branch is feature/login, the preview URL would be:

https://my-app-feature-login.yourdomain.com

Each individual deployment within the preview also gets its own URL:

https://{deployment-slug}.{preview-domain}

These per-deployment URLs let you compare different versions of the same branch.


Control which variables are included

Not all environment variables should be available in preview deployments. For example, you might want to keep production API keys or payment processor credentials out of previews.

Each environment variable has an Include in Preview toggle:

Exclude a variable from previews

  1. 1

    Go to your project's Environment Variables page.

  2. 2

    For each variable, check or uncheck Include in Preview.

  3. 3

    Variables with this toggle off will not be injected into preview environments.

    Checkpoint: Confirm production keys like STRIPE_SECRET_KEY show Include in Preview unchecked.

  1. Go to your project's Environment Variables page
  2. For each variable, check or uncheck Include in Preview
  3. Variables with this toggle off will not be injected into preview environments

When creating a new environment variable via the API, set include_in_preview: false to exclude it:

curl -X POST "https://your-temps-instance/api/projects/{project_id}/env-vars" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "STRIPE_SECRET_KEY",
    "value": "sk_live_...",
    "environment_ids": [1],
    "include_in_preview": false
  }'

Preview comments on pull requests

When a deployment runs for a branch that has an open GitHub pull request or GitLab merge request, Temps posts a single sticky comment on that PR/MR and updates the same comment in place as the deployment progresses — it never spams a new comment per build. This works identically on GitHub and GitLab.

The comment is keyed by a hidden HTML marker scoped to the project and environment:

<!-- temps-preview:project=N:env=N -->

On each update, Temps finds the existing comment carrying that marker and edits it; if none exists, it creates one. The comment body reflects the current phase of the deployment:

PhaseComment headingAdditional content
Building / in-progress🚧 Deploying preview
Succeeded✅ Preview readyPreview URL
Failed❌ Preview build failedLink to deployment logs
Cancelled⛔ Preview deployment cancelledCommit SHA + link to deployment logs

When a deployment is cancelled — from the dashboard or via the API — Temps updates the sticky comment to the cancelled state. Prior to this, cancelling a deployment would leave the comment stuck on 🚧 Deploying preview indefinitely. The cancelled body includes the commit SHA so it is clear which revision was stopped.

Required token scopes

For Temps to post comments, the connection needs write access to pull requests:

ProviderScope
GitHub Apppull_requests:write
GitLab tokenapi

Newly created GitHub Apps request pull_requests:write automatically. An existing GitHub App installation that predates this and lacks the scope will hit a 403 — Temps logs it and skips the comment, but you'll need to upgrade the app's permissions to get sticky comments.


Access preview URLs

Find the URL for any preview deployment:

  1. Open your project in the dashboard
  2. Click Environments in the sidebar
  3. You will see all environments listed — preview environments are marked with a Preview badge
  4. Click on a preview environment to see its URL and deployment history

Alternatively, on the Deployments page, each deployment entry shows its environment name and a direct link to the live URL.


Create environments manually

Auto-created previews cover feature branches, but you can also create environments by hand for long-lived branches like staging or develop. There is no default cap on the number of environments per project, so you can create as many staging, QA, or long-lived preview environments as your workflow requires:

Create an environment manually

  1. 1

    Go to your project's Environments page.

  2. 2

    Click New Environment.

  3. 3

    Enter a name (e.g. staging).

  4. 4

    Select the branch it tracks (e.g. develop).

  5. 5

    Configure replicas and resource limits (optional).

    Checkpoint: Confirm the new environment appears in the Environments list and is never soft-deleted when its branch is removed.

  1. Go to your project's Environments page
  2. Click New Environment
  3. Enter a name (e.g. staging)
  4. Select the branch it tracks (e.g. develop)
  5. Configure replicas and resource limits (optional)

Manual environments behave like auto-created previews but are never soft-deleted when the branch is removed.

Per-environment overrides

Each environment can override the project-level deployment configuration:

  • Name
    branch
    Type
    string
    Description

    The Git branch this environment tracks.

  • Name
    replicas
    Type
    integer
    Description

    Number of container instances. Default: 1.

  • Name
    exposed_port
    Type
    integer
    Description

    Override the container port. Default: auto-detected from the image's EXPOSE directive.

  • Name
    automatic_deploy
    Type
    boolean
    Description

    Whether pushes to the branch trigger automatic deployments. Default: true.

  • Name
    cpu_limit
    Type
    integer
    Description

    CPU limit for containers, in millicores (e.g. 500 for half a core).

  • Name
    memory_limit
    Type
    integer
    Description

    Memory limit for containers, in megabytes (e.g. 512).


Notify external systems with webhooks

Temps can fire outbound webhooks when a deployment changes state, so you can post a message to Slack, Discord, or any HTTP endpoint when a preview goes live or fails:

Add a deployment webhook

  1. 1

    Go to Settings > Webhooks.

  2. 2

    Add a webhook URL.

  3. 3

    Select the deployment events you care about (deployment.created, deployment.succeeded, deployment.failed, deployment.cancelled, deployment.ready).

    Checkpoint: Trigger a preview deployment and confirm your endpoint receives a payload carrying project_name, environment, branch, commit_sha, status, and url.

  1. Go to Settings > Webhooks
  2. Add a webhook URL
  3. Select the deployment events you care about

The available deployment events are:

EventWhen it fires
deployment.createdA deployment was queued
deployment.succeededThe build completed successfully
deployment.failedThe deployment failed (build error, health-check timeout, etc.)
deployment.cancelledThe deployment was cancelled
deployment.readyThe deployment is live and receiving traffic

Each deployment payload carries the project_name, environment, branch, commit_sha, commit_message, status, and the live url — enough to build a meaningful notification.


Clean up stale previews

Preview environments accumulate over time as branches are created. To clean them up:

Delete a stale preview environment

  1. 1

    Go to Environments in your project.

  2. 2

    Find the preview environment you want to remove.

  3. 3

    Click the Delete button (or use the actions menu).

    Checkpoint: Confirm the environment disappears from the list; its containers are stopped and removed and the record is soft-deleted, but the Git branch is untouched. Production cannot be deleted.

  1. Go to Environments in your project
  2. Find the preview environment you want to remove
  3. Click the Delete button (or use the actions menu)

Deleting a preview environment:

  • Stops and removes the running containers
  • Soft-deletes the environment record (it can be restored if the same branch is pushed again)
  • Does not delete the Git branch

You can also tear down individual deployments without deleting the entire environment.

Tear down a single deployment

  1. 1

    Open the Deployments page.

  2. 2

    Use the Teardown action on any deployment to stop its container and free resources.

    Checkpoint: Confirm the deployment's container is stopped while the environment stays available for future pushes.

On the Deployments page, use the Teardown action on any deployment to stop its container and free resources while keeping the environment available for future pushes.


Troubleshooting

Preview not created after a push

  • Verify that Preview Environments is toggled on in project settings
  • Confirm the push targets a branch other than the project's main branch
  • Check your Git provider's webhook delivery logs to confirm Temps received the push

Preview URL returns 404

  • The deployment may still be building — check the Environments tab for its status
  • If you serve previews from a custom domain, make sure a wildcard DNS record (for example *.yourdomain.com) points at your Temps server so every preview subdomain resolves

Preview returned 503 on first load (on-demand environments)

If an on-demand preview returned 503 Service Unavailable the first time you opened it, the container did not become ready within the configured wake timeout.

What to check:

  • Open the environment's Runtime Logs in the dashboard. If the container crashed or failed a health check during startup, the log will show the cause (missing env var, port mismatch, out-of-memory kill, etc.).
  • Check how long your container takes to start. If it takes longer than the wake timeout, increase the wake timeout in Settings > General (up to 120 seconds). JVM applications, containers that run database migrations on startup, and large images are common culprits.
  • Confirm the exposed port matches what the container listens on. Temps probes the port declared in the environment's exposed_port setting. If the container listens on a different port, the TCP probe never succeeds and the wake times out.
  • Retry the request. If the container did start successfully, a single retry immediately after the 503 will land on the now-running container. The 503 indicates the first request was the one that triggered the wake and then timed out waiting; subsequent requests see a running container.

If the preview consistently times out, increase the wake timeout or investigate the container startup logs to reduce cold-start time.

Variables missing in a preview

  • Confirm the variable has Include in Preview enabled
  • Variables are copied when the preview environment is first created. A variable added afterwards is not retroactively injected into existing previews — add it to the preview environment or recreate the preview

Was this page helpful?