The magic of preview environments
9 min read
In traditional monolithic systems, reviewing code was a relatively simple process. As the entire application is bundled as just one single component, building the entire project either locally, or in an online coding environment such as Replit or GitHub codespaces is all you needed to do to view the changes and see how they would work.
However, the story changes as we move to a microservice-based architecture. In a microservice architecture, the entire application is broken down into many small components which are designed to be their own self-contained applications. This means that these small components can run without depending on the other components in the architecture. Perhaps you can already see the problems that arise while reviewing changes to such codebases.
Since every application is a self-contained app, in order to review some code changes and see the impact of the change across the entire application i.e. when all the microservices are running and working together, you would need to build each and every microservice. While this type of architecture has benefits in a production system, it does make it difficult to review code and see the impact of changes across the entire application. This is where we can leverage the power of preview environments.
Why do we have so many environments?
Before the look at preview environments, let's try to understand why we have multiple different environments. By understanding this, we will be able to appreciate the benefits of preview environments even more.
In a system that runs on Kubernetes, i.e. an application or multiple applications that use a microservice architecture, we have many different environments. These environments all have different functions and use cases. Some of the common environments include a production environment, a staging environment, a QA environment, a local development environment, etc. Each of these environments has a different use case.
For example, the main use case for a local development environment would be to write code for the application. We talked about the complexities of building a microservice application earlier. You would need to build up many individual services and connect them to see the full extent of the code changes. In a local environment, this can be done either by using a docker-compose service or a local Kubernetes cluster such as Kind or Minikube.
The QA environment would be concerned with making sure that all the components are working correctly or not. The staging environment would be used to test the features before they are added to production. As you can see, there are tons of different environments for applications. There might be even more environments depending on the needs of the applications.
As such, it can be difficult to efficiently manage so many different environments. The environments might not all be the same either, which can lead to some problems. For example, a local development environment runs at a much smaller scale than a production environment. While the production environment might be using 100 microservices due to scaling, a local environment would have only a fraction of that number. As such, it can be difficult to anticipate problems that might arise in the production environment.
Why consider using preview environments?
We already talked about so many different kinds of environments. Now let us talk about one more environment called preview, or ephemeral environments. These are temporary environments that live for a short period of time before getting destroyed. Why would we want to have these kinds of environments? Let's first try and understand the entire workflow without using preview environments.
The first step in the entire process to add a new feature or existing one would be to write the code for the application. This would be done by a developer, someone who understands how to read and write code. After doing a bit of local testing, they will push the code to their git repository, whether it's GitHub or GitLab, and then open a PR/MR to merge the code for the new feature to the upstream repository.
Assuming that the best practices for git workflows are being followed, this feature would be opened in a new branch in the upstream repository. This is where other developers will be able to review the code for this new feature, point out bugs and suggest some improvements. However, the main point to note, is that the code review is being done by other developers, who also understand how to read and write code. Product teams, designers or other stakeholders will not be able to make sense of this code.
Once other developers review the code, it would get merged into the new branch, and this new branch would be visible in one of your test environments such as the staging environment. At this stage, the product managers, designers and other non-technical teams would be able to view all the changes to the application, use it and make sure all the functionality works as expected, etc.
Now let's say that the designer finds something that is wrong with the design, or the product manager finds that certain functionality isn't working as expected. Now it is back to the developers to update the code to make sure the problems are fixed. However, developers will need to do the entire process all over again. They will need to make a new branch, open a new PR, get it reviewed once more, and then push it to staging again.
This is quite a tedious process and wastes a lot of time as well as resources. It can also be an expensive process as your preview environments which are running in Kubernetes would use up more resources. Imagine the benefit if the product and other non-technical teams were able to preview the application in the PR itself before it gets pushed to staging. This not only can save time and energy but can also save money in the long run.
This is the entire idea behind a preview environment. These environments are automatically created when you open a PR and get destroyed once your code is merged into the main branch. Thanks to these preview environments, other stakeholders of the product are able to view the changes and provide feedback, just as developers would provide code reviews.
Preview environments are not beneficial only to non-technical teams. Oftentimes, when developers are asked to provide code reviews, they might be working on some other features. In order to provide a review, they would need to clone the changed code, and run it locally, which would disrupt their own development tasks. With the help of preview environments, they wouldn't need to go through the additional steps of cloning, and building the project. They can simply use the same preview environment to see the changes, and the code at the same time and make live changes as required.
What are some preview environments that can be used?
One of the most simple use cases for preview environments is for previewing front-end applications. This is easy to do by using services such as Netlify and Vercel. These services let you preview your code changes even before you push the code into your branch. This lets you create changes to the front end and view it in real time.
However, a front end is just a monolith. The process of creating these preview environments gets difficult as the application gets distributed between multiple microservices. It might even be distributed over 100s of microservers which makes it increasingly difficult to create preview environments for them.
The problem of creating a preview environment is theoretically solved for a local computer. On your local system, you can very easily create a docker-compose file, and use docker-compose to deploy all the components of the application locally. However, this is limited to your local environment, which means you are the only one who is able to preview the application. A proper solution would be if these local implementations can somehow be used on the cloud.
This is exactly what Preevy by Livecycle does in order to create some preview environments. Prevey is able to take your Docker Compose files, and instead of running it on a local system, it runs it in a VM on the cloud. Prevey can also create its own HTTPS links which allows anyone from your team to access the preview website after authenticating. If your Docker Composer environment is configured correctly in a local environment, using Preevy is as simple as running a simple preevy up
command instead of running docker-compose up
as you would for a local environment. Preevy can also run on your Kubernetes cluster and create environments inside your cluster itself.
Some challenges with setting up preview environments
The main problem with adopting preview environments in your entire development workflow would just be to solve the same issues that you face while setting up local environments.
While creating a local docker-compose environment, there are a few challenges you might run into. These challenges can range from incorrect container build instructions to configuration issues or even an issue with how the containers talk with each other. Another challenge lies in working with data. As we know, containers are ephemeral, which means they don't work very well for storing data. This can lead to a few challenges while working with databases and applications that rely on data.
In a nutshell, the only challenges that you will face while setting up a preview environment, are the same ones you face while setting up a local environment. If your docker compose environment works without any issues, then your preview environment which is created by Preevy will work in the exact same way.
Another challenge with preview environments arises if your microservices are in different repositories. Let's say that your front end exists in one repository, and your back end is in another repository. This poses a challenge while connecting the two separate environments. This is a little easier to solve if all the different microservices exist within the same repository.
You also need to make sure that your preview environments are performant, while also not increasing costs. Since the preview environments use VMs, it's easy to potentially create 100s of preview environments which might increase the costs exponentially. In this case, it is important to create and destroy these preview environments quickly and not let them live for too long.
Conclusion
In order to optimize your development workflows, and allow other stakeholders to review changes to the application before pushing your code to a staging environment, it's important to use preview environments. They help reduce the time and effort needed to make a change, and changes can be made instantly within the PR itself.
Instead of pushing the changes to a staging environment and then getting the changes reviewed, you can simply review them inside the PR itself. This saves both time and energy and if done right, can save costs as well.
Try setting up some staging environments for your repositories using Preevy.
You can also check out the documentation to help you get started.