Jan 2020
With Heroku Pipelines and Figaro
This is probably one of the most boring posts on the internet, but I’m planning to forget the following in 30 seconds, so let’s write it down quickly.
We’re building a Rails application that uses a Postgres database, Redis, Sidekiq, and Puma.
A default rails app will try to use the environment variable RAILS_MAX_THREADS
in a lot of these places.
How to choose your RAILS_MAX_THREADS
depends on a lot of things that are out of the bounds of this blog post or my understanding. Heroku has some good info if you’re curious.
Where is RAILS_MAX_THREADS
being reused?
Currently, we’re using RAILS_MAX_THREADS
in our:
puma.rb
config (this is the web server that runs the app).sidekiq.yml
config (this is what we’re using to run jobs)database.yml
config (how many connections the app can make with the database)
Where to put RAILS_MAX_THREADS
?
Since we’re reusing RAILS_MAX_THREADS
in many places, where should we put this global variable so that it’s available where it needs to be?
Where not to put them?
Our couple attempts at setting this up failed, we at least we know a couple of places where we shouldn’t put them.
(1) Don’t put RAILS_MAX_THREADS
in your Credentials
file. This is because our Credentials file is not available to things in our config
folder (puma.rb
, sidekiq.yml
, etc.). This appears to be a timing thing, as the config
files are parsed before the app is built (and Credentials
generated).
(2) Don’t put RAILS_MAX_THREADS
in a confusing global variable. Initially I created a global.yml
file containing the RAILS_MAX_THREADS
in config
. Then, I added:
GLOBAL_SETTINGS = YAML.load_file(Rails.root.join("config/global.yml"))
to an initializer, assuming I’d be able to call
<%= GLOBAL_SETTINGS["RAILS_MAX_THREADS"] %>
inside the config
folder.
Nope, this doesn’t work, probably for similar reasons as number 1 above.
Where to put them?!
For each environment, we will be able to access our RAILS_MAX_THREADS
as
<%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
where 5 is just the back-up value if the ENV var is not found.
Development
For DEV, we use the Figaro Gem, which allows us to specify ENV variables in an application.yml
file.
Even though our max_threads isn’t too sensitive, application.yml
is ignored from version control, in case we end up adding more ENV variables later on.
# application.yml
development:
RAILS_MAX_THREADS: 5
RAILS_MIN_THREADS: 5
Review Apps
We’re using Heroku Pipelines, so we create Review Apps every so often.
Rather than having to manually set the ENV variables for each Review App, we can specify the ENV variables in our app.json
. This file lays out details about how our new heroku apps will be built.
{
"description": "Learning and Teaching",
"website": "https://bounce.so",
"env": {
"RAILS_ENV": "staging",
"RACK_ENV": "staging",
"RAILS_MAX_THREADS": "10",
"RAILS_MIN_THREADS": "10"
}
...
}
Note that strings are required for environment variables in our app.json
.
Staging App
Perhaps we want our RAILS_MAX_THREADS
to be different than our review apps, because we’re trying to mimic production here, (and have the associtated bigger plans).
For this, we’ll go into our config vars on heroku and manually set them. This can be done from the UI or the terminal. this isn’t too much of a pain, because this only really needs to be set once, or any time we want to tinker with performance.
Had the app.json
been loaded with that env variable from the start, our config vars for Staging would already have the thread value set (though of course we can override it).
Production
Same story as Staging, we can manually update them on Heroku dash, or via command line.
Conclusion
Congratulations on reading the most boring post on the internet. There are others that rival this elsewhere on the site if you’re interested.