Home pageGimlet

Don't group environment variables

Laszlo Fogas
Laszlo Fogas
2023-04-03
NaN

At Gimlet.io, we have a consulting background. We join teams who want to adopt containers and Kubernetes, and we create the guardrails for developers who want to efficiently use these technologies.

Nowadays it is called platform engineering, but when we started these projects - and made our off-the-shelf IDP, Gimlet - it was just called devops tooling work.

tldr: we see hundreds of apps every year.

There is one particular practice that popped up recently more often than we would have expected, and that is grouping environment variables.

Grouping environment variables

If the term does not ring a bell, it is the practice when an app requires a variable like APP_ENV, takes predefined values like staging or production, then there is a switch case in the code that sets further values based on the environment.

If APP_ENV equals staging, use this database connection string, if production use another. You get the gist, kind of like NODE_ENV and RAILS_ENV, but supercharged.

We are not saying that those frameworks promote a bad practice, but we do believe that developers get inspired by this environment concept and sometimes build hard to change assumptions into the code about the environment the app runs in.

This bad practice was well described in the The Twelve-Factor App methodology, which by the way is twelve years old this year. This post is a periodic reminder about the practices 12factor promotes and an example how grouping environment variables makes devops life difficult.

An example how this practice makes devops life difficult

With grouping, assumptions about the environment are built into the code. Limiting the ability to reconfigure the application on-demand.

One common situation when someone wants to deviate from the built in assumptions is in case of incidents. When a database is down and restored on a different url, or when network traffic is rerouted due to a networking failure.

It happened to us during a disaster recovery plan rehearsal. It is one of the better times to reveal this bad practice, as it turned out many of the applications take database parameters in the form of environment flags, and hostnames of services that a given app depends on were also controlled by the environment flag.

export const BACKEND_URL = {
  development: 'https://xx.staging.mycompany.com',
  staging: 'https://xx.staging.mycompany.com',
  production: 'https://xx.mycompany.com',
}

This practice may have helped codifying development setups, but during the disaster recovery rehearsal, it meant that we needed to change many of the apps so they take BACKEND_URL directly from the environment. Practically, it meant pull requests and waiting.

Grouping environment variables causes friction

Just like a developer doesn't like to wait on an infrastructure component being created, operations people don't like waiting on application changes.

By following the best practice from 12factor.net and exposing every configuration value as an environmet variable, the friction is eliminated, and you may also have improved the incident recovery time.

Onwards!

More from our blog

Clickops over gitops

Doing cloud operations by clicking on a dashboard that generates a stream of infrastructure as code changes.

The how and why we built our SaaS platform on Hetzner and Kubernetes

Hetzner is 5 times cheaper for us than the hyperscalers. This blog posts enumerates the how and why we built our SaaS on a discount bare metal provider. Gotchas included.

Announcing the Gimlet SaaS Early Access

We have something really exciting to share with you: Gimlet is going SaaS. In other words, you will be able to use Gimlet's unparalleled Kubernetes deploy experience with even fewer clicks than before.

How Flux broke the CI/CD feedback loop, and how we pieced it back together

A green build used to mean a successful deploy. But then gitops came and broke this heuristic.

Are you sure none of your containers run as root?

The Kyverno policy engine just arrived in Gimlet Stack. Let's see how you can be certain that none of the containers run as root in your Kubernetes cluster.