Learn how Preview Environments can streamline your development process and help your team deliver quality software on time.
Preview Environments aka Ephemeral Environments help software teams increase their development velocity by reducing the time it takes to test and release new features
Preview Environments aka Ephemeral Environments are created on-demand for testing a specific git branch before it's merged. Preview Environments— unlike persistent Staging or Production Environments—are intended to be short-lived and single-purpose, existing only as long as they are needed to test a specific feature or bug fix. Preview Environments often share the same lifecycle as the event that triggered it, typically a pull request/merge request. That is, they're created when a PR is opened and destroyed when the PR is merged or closed; alternatively, they may also be set to timeout after several hours.
Preview Environments help software teams increase their development velocity by reducing the time it takes to acceptance test new features. They enable faster reviews, rapid feedback, and iterative cycles. They enable teams to standardize a best practice for code review, and they ultimately reduce the workload on maintainers and team leaders who are responsible for dozens of pull requests every month.
Preview Environments empower teams to shift their testing process to “pre-merge” where it’s significantly easier to find bugs, isolate responsibility, and make the appropriate changes. You can think of Preview Environments as a quality gate that allows features to be thoroughly tested and iterated upon in isolation. The net effect is feature parallelization or what is sometimes called “shifting left”. This is why we say, “Don’t merge until you preview” or “Keep dirty code out of main.”
Preview Environments fill the gap between local testing and your Staging environment or Production Environment. They are designed to test individual features or topic branches in a production-like environment that includes a full-stack of services. They have a purpose-driven or ephemeral life-cycle which means that they exist only as long as they are needed for review. Configure it to create efficiency when you deploy code changes.
In practice, Preview Environments are most often created and deleted in response to a pull request (PR) or merge request (MR) trigger.
A Preview Environment is often synonymous with pull requests (PR) environments, on-demand environments or ephemeral environments, with implementation details varying depending on the use case. When a new pull request comment is created a Preview Environment is also created. When the PR is updated the Environment is updated. And when the PR is merged or closed the Environment is deleted.
With preview environments, you give your team the capability to have as many test environments as you need, when you need them, and only for as long as you need them. They primarily benefit maintainers and team leads who are overall responsible for speed of delivery and code quality but they are also a great cross-functional team tool because they benefit developers, testers, product team, and other key stakeholders.
As platforms like Netlify and Vercel have popularized previews for frontends and visual changes, the newly emerging preview environment is a natural complement for backends, databases, APIs, CLIs, Binaries, and, in general, any microservices application. Many consider the capability to be a “game changer” and the “holy-grail” of DevOps.
Below are common benefits when preview environments become an integral part of your development process.
Preview Environments enable fast cycles for every Pull Request - this accelerates how quickly you can review, provide feedback, and complete acceptance testing.
Feature fratricide and co-dependency is a major problem as teams try to grow and scale against a shared environment. Preview Environments enable you to decouple each Developers contributions from each other so as soon as a new feature is ready it can be released - you don't have to worry about bugs being introduced that are unrelated to any specific feature.
Development Team leads and open-source maintainers bear a huge amount of responsibility. To mitigate merge risks they will often want to see a running version of a Pull Request before they approve it.
Without Preview Environments this means pulling down the branch and running it in their local dev environment. This, of course, can be time consuming—multiply it by the number of developers on the team, and this becomes their whole job. More importantly each maintainer may do this with a different environment set-up which makes standardization impossible and makes for an inefficient code review and deployment cycle. If your application has a number of dependencies the challenge here is multiplied.
Identifying bugs prior to merging will save time and headaches for your Development Team lead. If you merge buggy code to a trunk branch, you’ve made an unforced error.
You won’t be able to cut a new release to production without 1.) Reverting your changes (=RISKY) or 2.) Waiting for the bugs to be fixed. And, of course, if you’ve broken a shared environment all testing will grind to a halt.
With a Preview Environment you can review code in a standardized, holistic way which drastically improves the odds of catching bugs early. You can use Preview Environments to run automated tests or conduct manual exploratory testing—either way your team lead will thank you for keeping dirty code out of a trunk branch.
Ensuring continuity between what is designed and what is implemented is a ubiquitous organizational challenge. Preview Environments solve this by enabling your team to bring in all the key stakeholders early in the process.
Would you rather find out the product owner doesn’t like how something was implemented right after you code it, or a week later when they see it for the first time? Create end to end visibility across your entire organization.
Preview Environments enforce a best practices process that can be replicated across all of your teams.
For example how one team lead pulls code to run in their local environment will not necessarily match how another does it. Preview Environments as part of your Continuous Integration represent a best practice that all teams can follow.
Continuous is a term that represents something every team strives for, hence continuous integration, continuous delivery and continuous deployment. Continuous testing is no different. Finding issues earlier in the Software Development Life-cycle benefits everyone. Preview Environments are designed to be rapidly created and updated to enable continuous testing - either manual testing, automated testing, or ideally both.
As automated testing matures for any project, the queue against a single or limited number of environments becomes its own bottleneck.
This “queuing effect”—waiting up to several hours for tests to run—will only grow over time and continue to slow your team down. A Preview Environment enables faster feedback loops. Previewing can be done in parallel so that a single buggy commit does not hold up the entire forward progress of all the working commits.
Unlike traditional QA or staging environments which often become polluted over time from data accumulation and conflicting commits, Preview Environments are ephemeral and intended to test a single topic branch. Once they reach the end of their useful life, their resources—including their data—are destroyed. This design isolates developer responsibility and simplifies root cause analysis since each environment is associated with a single feature or bug fix. The dynamic nature of Preview Environments, however, presents some unique challenges that are not present in persistent test environments.
Reviewing against a relevant set of data is critical to the process for many applications. For Preview Environments to be effective in this scenario the database needs to be seeded with a relevant set of data. To learn more about how to solve this problem check our section on Data for Preview Environments.
If you are relying on various managed cloud-based services you can "mock" those services in your Preview Environments. Common services like Postgres, MySQL, Redis can easily be run as containers and if you need something AWS specific like Lamda or S3, you can pull these "mock" containers from Localstack's public Docker Hub repository.
If you have a stateful service that cannot be represented as a container or a virtualized service, then you probably want to connect to it read-only, or not connect at all. If this is a sticking point for your particular application, you will want to look for an infrastructure-as-code based-solution that can help you create/delete instances of your managed service for your Preview Environment.
Connecting environments to serverless platforms like AWS Lambda can be a point of friction. Fortunately many of these can be containerized as an effective substitute to run in your Preview Environments.
Often many services will depend on calls to a static URL (i.e. qa.acme.com). Preview Environments have a dynamic URL which means you may have to do some work to ensure that your team can dynamically interact with key dependencies.
If dynamic URLs follow a predictable format as they do on Uffizzi, that can drastically simplify connecting to other services in a predictable and dynamic way.
At Uffizzi we are actively working on a solution to enable dynamic updating of backlinks to key services like OAuth and we look forward to posting about that in our Preview Environments Guide.
For certain teams and applications it may make sense to create your own preview tool, but we highly recommend avoiding this route if possible.
It’s extremely costly for two, three, or more engineers to set up, build, and maintain a custom preview environment tool—especially since there’s handful of solutions on the market that will likely fit your needs and which are constantly improving.
For teams who want Preview Environments on their own infrastructure, open-source Uffizzi is the only self-hosted solution of its kind. And for teams that want Environments as a Service, Uffizzi Cloud provides the fastest way and most low maintenance way for teams to get started.
Uffizzi integrates with any version control system, CI-provider, and container registry. Define your applications with Docker Compose, then use one of our GitHub Actions workflows or GitLab jobs for easy integration.
How Team Uffizzi went from releasing once per week to once per day
To wrap up 2022 we ran a year end Survey to gather current opinions on Preview Environments from a wide audience of experienced software engineers whose roles range from individual contributors to CTOs and whose experiences range from Open Source Projects to Enterprise. The results are in, and we’re excited to share them with you!
This practical guide illustrates how to incorporate ephemeral Preview Environments into your development workflow. The result is more rapid releases through greater efficiency and development speed.
Using shared, persistent test environments creates an overly complex and bottlenecked workflow that represents an inherently flawed process in a software development lifecycle (SDLC). Going ephemeral breaks your team free from the co-dependent nature of shared environments and provides a system that enables extremely fast release cycles.
This is the ephemeral environment playbook that we created internally at Uffizzi and that we use to average a release every working day. Uffizzi ephemeral environments fill the gap between your local development and production to expedite code reviews, testing, merge times, and release velocity.
In this article we discuss two strategies for seeding database instances for each of your ephemeral Preview Environments.
Previews simplify the testing process by replacing a polluted QA environment with a clean and ephemeral test environment for every feature branch. But what if your application depends on a stateful service like a database? How can you include persistent test data or other stateful configurations in each of your Preview Environments? In this guide we discuss important design considerations for database seeding in ephemeral environments along with specific techniques you might consider to add seed/test data to your Preview Environments.
Depending on your application and test data requirements, you can use one of the following methods to seed database instances for each of your Preview Environments:
With either of these methods, the test data can be stored in your repository or object storage, depending on the size of your data set and how frequently it gets updated.
Add previews to your pipeline with the official Uffizzi reusable workflow for GitHub Actions.
Uffizzi integrates as a step in your GitHub Actions pipeline to manage on-demand, ephemeral test environments for every feature branch/pull request. We've published a reusable workflow for your GitHub Actions. This can handle creating, updating, and deleting Preview Environments. It will also publish Preview Environment URLs as a comment to your pull request issues.
If you want Uffizzi to build container images for you (instead of a CI provider like GitHub Actions), you can use our built-in CI solution.
If you don't have an existing CI solution, Uffizzi CI can build your application from source and store your container images for you. Please note that your source code must be stored in a GitHub repository to use Uffizzi CI.