RACK_ENV: It's not *for* you

Posted: Sun, 13 October 2013 | permalink | 3 Comments

(With apologies to Penny Arcade)

I’m probably the last person on earth to realise this, but the RACK_ENV environment variable (and the -E option to rackup) isn’t intended for consumption by anything other than Rack itself. If you want to indicate what sort of environment your application should run in, you’re going to have to do it via some other means.

Why is this? Because the interpretation that Rack applies to the value of RACK_ENV that you set makes no sense whatsoever outside of Rack. Valid options are “development”, “deployment”, and “none”. If you follow the usual Rails convention of naming your environments “development”, “test”, and “production” (and maybe “staging” if you’re feeling adventurous), then in any environment other than “development”, you’re not going to be telling Rack anything it understands.

As I said, I may be the last person on earth to have worked this out, but I doubt it. There are plenty of bug reports and “WTF?” blog posts and Stack Overflow questions that appear to stem from people misunderstanding the purpose of RACK_ENV. Sadly, the Rack documentation is very quiet on the whole topic, and the only place that mentions how the environment is interpreted is in the comments for Rack::Server.new – and that doesn’t tie that environment to the -E option or RACK_ENV environment variable.

At any rate, the take away is simple: unless you want Rack to pre-configure a bundle of middleware for you, RACK_ENV or rackup -E is not the configuration variable you’re looking for. Use something else to tell your app how it’s supposed to work.


3 Comments

From: Scott Muc
2014-02-12 06:14

Nope, you’re not the last person. It looks like those that have used RACK_ENV to mean a conceptual environment name have just had things work by coincidence.

Thanks for the post. I’m going to make sure that RACK_ENV is one of the valid options in my projects and refer those that disagree to this post. I know Sinatra is guilty of overloading the purpose of this variable.

From: Dennis
2015-01-08 01:10

It seems that in some cases we have little choice when it comes to changing RACK_ENV.

For example, if you use dotenv-deployment for managing your app’s .env files for different environments, then (unless I’m missing something) you’re forced to change RACK_ENV.

This is because it determines the environment like this ruby if environment = ENV['RACK_ENV'] || (defined?(Rails) && Rails.env)

As you can see, RACK_ENV takes precedence.

If you use Heroku and run heroku config, you’ll see that Heroku sets RACK_ENV=production (it also sets RAILS_ENV=production).

So if you have your staging and production environments on Heroku, and you have your staging and production configuration files (i.e. config/environments/{staging,production}.rb), then you’ll need to set the env vars that Heroku uses appropriately – you’ll just have to modify the staging values for RACK_ENV and RAILS_ENV since production already has the correct values by default.

I hope this doesn’t break anything I’m not aware of fingers crossed. I’m not really sure yet how RACK_ENV is used by Rack (and whatever else may be using it), so I’m just treading in the dark right now.

From: Matt Palmer
2015-01-08 08:11

Hi Dennis,

Thanks for your comment.

Yes, it does suck rather a lot that various other applications have latched onto RACK_ENV and are misusing it. It’s rather the reason why I wrote this post originally (although I didn’t specifically call out framework and library authors, as I probably should have).

It seems to me that dotenv is definitely doing it wrong (way, way wrong), although Heroku is (probably) doing it right – they should be setting RACK_ENV (because they’re using Rack compatible appservers). The problem only comes when everyone else uses RACK_ENV, as well, instead of having their own environment variable. I universally set RACK_ENV to none, because that’s the behaviour I want out of Rack; so very, very many other things freak out. Practically speaking, though, it doesn’t bother me as much as it used to, because I’ve moved from using database.yml-style configs-in-files to configuring everything via individual environment variables, because that’s so much more flexible, and doesn’t require hard-coding all sorts of things about the app environment in the codebase.

To answer your last question, Rack itself uses RACK_ENV primarily for setting a default middleware stack (as per the docs for Rack::Server.new and the related code. The astute reader will note that the docs and the code don’t match, which amuses me too much to be willing to ruin it by submitting a pull request.

Post a comment

All comments are held for moderation; markdown formatting accepted.

This is a honeypot form. Do not use this form unless you want to get your IP address blacklisted. Use the second form below for comments.
Name: (required)
E-mail: (required, not published)
Website: (optional)
Name: (required)
E-mail: (required, not published)
Website: (optional)