Skip to content

What is an ephemeral environment?

An ephemeral environment is a short-lived, full copy of an app made for one change or pull request and then deleted, e.g. a preview environment.

Last updated , 8 min read

What is an ephemeral environment?

An ephemeral environment is a temporary, complete copy of an application that a team creates for one change or test run and deletes afterwards. A preview environment is one kind, built for one pull request, with its own URL where reviewers can try the change. Other names for a preview environment are review app and pull request environment.

The copy runs the app with the services it needs, e.g. a database, and no other change shares it. The continuous integration and delivery (CI/CD) pipeline usually creates a preview when a pull request opens and deletes it when the pull request merges or closes. Other ephemeral environments last one test run, e.g. the app and database that a pipeline job starts for its tests.

The Wikipedia article on deployment environments lists the usual tiers, from a developer's machine to production. Most tiers keep running and hold many changes, e.g. a staging environment. An ephemeral environment adds a temporary tier for each change.

A sandbox for a coding agent is often deleted after use too, but its job is to limit what the agent's commands can reach. A preview runs the finished change for people and tests to try.

How is an ephemeral environment created?

A pipeline usually creates and deletes a preview environment in these steps:

  1. A developer or a coding agent opens a pull request, which starts the pipeline.
  2. The pipeline builds the change, ideally with the same build scripts that production uses.
  3. The pipeline deploys the build to an isolated place with a unique name and URL, e.g. its own Kubernetes namespace.
  4. The pipeline starts the services the app needs and loads known test data and test credentials. Loading and resetting that data is part of test data management.
  5. The pipeline runs a smoke test and posts the URL on the pull request for reviewers.
  6. The pipeline deploys each commit pushed to the pull request to the same environment.
  7. When the pull request merges or closes, the pipeline deletes the app, its data, and its URL.
The life of a preview environment a fix commit deploys again Pull request opened Pipeline build, deploy, seed Preview own URL and data Checks tests and reviewers Pull request merged or closed Deleted app, data, and URL
Each pull request gets its own running copy of the app. Checks run against that copy, and the copy is deleted when the pull request ends.

The code host supplies the trigger. In GitHub Actions, a workflow on the pull_request event runs by default when a pull request is opened, reopened, or updated with commits (the synchronize activity type). A workflow that deletes the preview lists closed in its types keyword, and a merged pull request also counts as closed. A types list replaces the defaults, so a workflow that also deploys lists all four types. A single workflow can deploy and delete the preview:

on:
  pull_request:
    types: [opened, reopened, synchronize, closed]
jobs:
  deploy:
    if: github.event.action != 'closed'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/deploy-preview.sh "pr-$(jq .number "$GITHUB_EVENT_PATH")"
  teardown:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - run: kubectl delete namespace "pr-$(jq .number "$GITHUB_EVENT_PATH")"

GitLab calls these environments review apps. Some hosting platforms build a preview for each pull request without a pipeline of the team's own. Some setups also delete a preview that has sat idle for a set time, so a forgotten one stops costing money. A preview URL often needs a login, because it exposes unreleased features and test data.

What is an example of a preview environment?

Here is an illustrative example. Acme Co. sells furniture online. A developer asks a coding agent to "Let customers edit their delivery address during checkout." The agent changes the checkout code, its unit tests pass, and it opens pull request #318. The pipeline deploys the change and posts this summary on the pull request:

Preview for pull request #318 is ready
URL:    https://pr-318.shop.example.com
Data:   20 test customers, 45 products
Smoke:  home, cart, and checkout pages loaded

The preview then goes through these steps:

  1. A product manager at Acme opens the URL, adds 2 items to the cart, and changes the delivery address. The address saved, but the cart emptied.
  2. The product manager comments on the pull request with those steps, and the agent fixes the checkout code and pushes a commit.
  3. The pipeline deploys the commit to the same preview at the same URL.
  4. The product manager repeats the steps, and the cart still holds 2 items.
  5. The pull request merges, and the pipeline deletes the preview, its database, and its URL.

The smoke test passed because it loaded pages and never changed an address. Without the preview, the first place the product manager could try the change was a shared environment after the merge. This example is simplified. A real preview would also need seeded data for odd cases, e.g. a customer with no saved address.

What changes when a coding agent writes the code?

A coding agent usually stops once its pull request is ready for review. Its "done" describes its own tests, which ran in a workspace that may not run the services the app depends on, e.g. its database. The preview is often the first place where the whole change runs as an app.

The pipeline deploys the preview after the agent's last push, so the preview's results arrive after the agent has finished. A background coding agent works without a person watching, so the preview can sit unopened until review.

A pull request from an agent can also edit the build and deploy scripts. The pipeline can run those edited scripts with the credentials it gives its deploy job, so a script can read those credentials or send them elsewhere.

A practical adjustment is to run end-to-end tests against each preview before a person reviews it. Post the results on the pull request, where the agent's next session can read them. Give previews test credentials only, and limit deploy credentials to preview resources.

What does an ephemeral environment not catch?

An ephemeral environment runs a change but checks nothing by itself. A preview that nobody tests shows only that the app started. Even a tested preview misses these problems:

  • Differences from production. A preview predicts production only as far as the two match, which is called environment parity. The Twelve-Factor App warns against using "different backing services between development and production." Previews also often run on smaller servers, with third-party services in test mode.
  • Real data. Seeded data rarely holds the odd records that production builds up. A migration that fails on old rows, e.g. orders with no delivery address, can pass in a preview.
  • Conflicting changes. Two pull requests can each pass in their own preview and break when both merge, so continuous integration on the main branch still has to check the combined code.

Each preview costs compute and setup time, which grow with the number of open pull requests. A preview earns more trust when the pipeline builds it with production's scripts and service versions, its data covers odd cases, and someone reads its check results.

How is an ephemeral environment different from a shared environment?

A shared environment, also called a persistent environment, keeps running between changes and holds many of them at once, e.g. a staging environment. Its data and settings build up over time, so a failure there can come from someone else's change. One broken deploy can also block everyone who uses it.

An ephemeral environment holds one change and starts clean each time, which gives each change test isolation at the level of the whole environment. Both kinds run the whole app, and both predict production only as far as they match it. Shared environments still have a job, because they run merged changes together.

How does RunStory help with ephemeral environments?

A preview environment gives a change a place to run, but someone still has to try the workflows the change touches. RunStory runs your software in a separate environment, tries relevant workflows, and checks the results. It is in private alpha for CLIs and web apps, and the alpha tests your software in isolated sandboxes. Your team keeps the final release decision.

Join the RunStory alpha →

FAQs

Why do developers use ephemeral environments?

Developers use ephemeral environments so that each change runs as a whole app before it merges, apart from other changes. Reviewers can try the change at its own URL, and tests run against a clean copy instead of a shared environment that other changes have altered.

Why should a preview environment resemble production?

A preview environment should resemble production because a check there predicts production only as far as the two environments match. A preview with different backing services or smaller servers can pass a change that fails after release. Building both from the same scripts narrows that gap.

What makes a good preview environment?

A good preview environment is built from production's scripts and service versions and loads seeded data that covers odd cases. It holds test credentials only and gets its own URL behind a login. Smoke and end-to-end tests run against it before review, and the pipeline deletes it when its pull request closes.

How long should an ephemeral environment live?

An ephemeral environment should live only as long as the change or test run it serves, usually until its pull request merges or closes. An idle limit deletes previews that nobody closes. Starting each copy from scratch keeps leftover data and settings from building up.