Preview Environments' Dependencies
Let's talk about databases, queues and other dependencies isolation
Following up on a previous article about deploying preview environments:
Introduction
Once you setup your preview environment and your pods are being deployed from your Pull Requests, how do you isolate other dependencies like Databases, queues or events in order to avoid Side effects.
Some hiccups you could encounter are database migrations, and removing initContainers like we did for the purpose of our previous article is not really a solution. Database migrations might not be part of the initContainers but run at startup of your service.
Context
Depending on the size of your company and the different teams working on the infrastructure, you might already have solutions like being able to clone an entire “stack” of services and dependencies to create complete isolation.
Look at Qovery for instance, but most of the big companies create their own IDP (Internal Developer Platforms).
This article is not here to talk about IDPs, but more give an answer for those of you that are in startups or small companies which don’t have an IDP yet.
Solution
Since you don’t have time neither resources to create a fully isolated and cloned environments, and it’s not just about doing it but also maintaining it..
In the end, what matters is to create enough isolation to avoid side effects, any solution that achieve that is great to start with.
Queues
Best is to start with something simple, for example if you use a Queue and you don’t want the events from your Preview Environments to mess up staging, then use environment variables to prefix your Topics / Subscriptions.
Databases
Database is a bigger subject, database migration could break your staging every time a preview environment gets deployed. Then how do you roll back, how often will you need to roll back ?
Moreover, not doing those database migrations might prevent you from testing your preview env.
External Platforms
There are some platforms like PlanetScale, Xata, Supabase and many others that host for you some of the infrastructure you need and let you programmatically spawn new instances easily. It saves you time but comes at a cost.
Simple
You could, as part of your Github Actions, recreate a new DB instance. If your DB is an actual pod, it would be easy, however if it’s part of the Cloud offering you would need more permissions to create a resource there (and it takes time and cost you more).
Then, you would have to import the latest DB backup from staging.
Ex:
Postgres Staging Instance:
- staging
- table 1
- table 2
Postgres Preview 42 Instance: (temp db instance)
- staging
- table 1
- table 2
- table 3 (from migration)
Simpler
There is an even simpler solution, instead of creating a pod or an instance of your DB, you could simply connect to the Staging DB and create a prefixed “database” inside it, import the latest DB backup into it, and run your migrations and queries in there.
Either way, your preview env needs update its environment variables to match the uniquely created database or DB instance.
Ex:
Postgres Staging Instance:
- staging
- table 1
- table 2
- preview-42 (temp database)
- table 1
- table 2
- table 3 (from migration)
Cleanup
Don’t forget to cleanup, whatever solutions you use. The database instance or the database inside your staging instance should be removed once your preview is being cleaned up.