---
title: Zero-downtime with Rails credentials part III
teaser: Transitioning the codebase from using environment variables to Rails Credentials
  for Zero-Downtime Deploys.
tags: ruby,rails,credentials,environment variables,devops,sre,infrastructure,zero
  downtime with rails credentials
author:
- Sami Birnbaum
- Valeria Graffeo
published_on: 2025-02-25
---

This post is part of the [Zero-downtime with Rails credentials] series.

In the [first post] we talked about the reasons that moved us
towards making a codewide change and adopt Rails credentials rather than using
environment variables to manage our secrets.

In the [second post] we saw what that means to us in our codebase in practice,
and how to structure the files necessary to use Rails credentials in each environment
within our application.

We left you hanging with a big question, whether we still need an `.env` file after all.
Here's the answer...

### Credentials don't fully replace `.env`

In an ideal world we would not need to have a `.env` file at all.

When we originally started this task, we thought credentials would replace
environment variables in their entirety.

However, as you may have already guessed, at the very least we
need 2 environment variables even when using credentials:

- `RAILS_ENV`
- `RAILS_MASTER_KEY`

`RAILS_ENV` tells the application which environment it is when it loads
and guides the application towards the correct credentials file for
that environment.

`RAILS_MASTER_KEY` allows Rails to decrypt the credentials.

Without these 2 environment variables, Rails would not be able to
infer which credential file to use and how to encrypt it.

### Load Differences

We may also have other environment variables that still need to
be defined apart from `RAILS_ENV` and `RAILS_MASTER_KEY`.

This is because environment variables are available when the app loads
at an earlier stage than Rails Credentials.

This is one of the drawbacks of Rails Credentials, unlike
environment variables, they live within the application, so they
require the application to load before they are available to use.

Therefore, some environment variables that we use during the loading
of the application may need to remain as environment variables.

These are mainly in files that live in `config/` or `initializers/`.

## OK, well, surely if we still have `.env` files then we can't use hot reloading and achieve zero-downtime?

Don't worry, we can, and we will!

The only issue with using hot reloading with environment variables
is that hot reloading does not pick up any changes to those
environment variables.

However, we have now distilled our `.env` files to only house
minimal environment variables that we do not expect to change and
should not change.

The vast majority of key value pairs have moved to credentials
and changes to them will be reflected with hot reloading [puma].

However, if for some reason, we did make a change to an environment
variable then we would need to restart the puma server for this change
to be picked up.

### Where do I put things going forward in `.env` or credentials?

It's a great question!

We think that by default _we should always endeavour to use Rails Credentials_.
This protects us from being able to change the values without
having downtime and also has the added benefit of storing things inside
the application which will be easier to manage.

However, if you are adding something that needs to read before the
credentials have loaded than you can add it to the `.env` file.

Now that we have Rails credentials in our application, we want to explore how
to use them in our test suite.
Stay tuned for the next article, about stubbing Rails credentials in specs and
other caveats.

[Zero-downtime with Rails credentials]: https://thoughtbot.com/blog/from-environment-variables-to-rails-credentials
[first post]: https://thoughtbot.com/blog/from-environment-variables-to-rails-credentials
[second post]: https://thoughtbot.com/blog/from-environment-variables-to-rails-credentials-part-two
[puma]: https://github.com/puma/puma
