> To me environment variables make only sense for secret things

A "secret" thing should be your database connection or redis credentials. I 
consider this "configuration".

> config options which change often or options you want to be able to change 
> without a redeployment.

I'm less concerned about how often you need to change the config var, but more 
concerned about how sensitive it is and how bad would it be if you used the 
wrong thing in the wrong place.

> Also is RAIL_ENV=staging rake ...
instead of RAIL_ENV= production rake ... some thing to prevent a big mistake 
just in case I did choose the wrong console.

Most people who are running a "staging" environment will have 
`RAILS_ENV=staging` in the environment (via bash profile or config vars on 
Heroku). Most people would just run `rake db:drop` (or whatever) without 
specifying the `RAILS_ENV`. So in the case you're in the wrong console, you're 
screwed because `RAILS_ENV=production` would be set.

If you're using production & staging "environments" what can happen is you're 
debugging some strange behavior and you accidentally do something like `export 
RAILS_ENV=production` to see if it matches the behavior in staging, then you 
run `rake db:drop` a few seconds later then, oops you just dropped your 
production database. Why did your staging app need access to your production 
database credentials? It didn't and should have it. If you were storing that 
data in the env instead of on disk via a config file you wouldn't have hit that 
problem.

(granted this specific problem is extremely unlikely due to a patch I had in 
rails https://github.com/rails/rails/pull/22967, but the general unsafe nature 
of your staging app being able to modify production systems still stands, maybe 
it's flushing your redisdb. You get the idea).

> I think there are a lot of good reasons to use multiple environments. Of 
> course a staging, integration or sandbox environment should be as close as 
> possible to production, but only close and not equal.

I think it should have the exact same behavior. The point of staging is to be 
able to tell if things will work in production. So if it has slightly different 
behavior, it's not a reliable indicator of if production will work. I'll give 
you an example.

I had a customer who had a bug with the asset pipeline in prod but not staging. 
It turns out have weeks of debugging they had view caching enabled in prod but 
not in staging which was causing an old link to an asset to be shown on 
production, but the bug didn't reproduce on staging. This is an area where 
staging should have seen the bug but the __behavior__ was different. Prod and 
staging should have the same behavior.

Where they differ should be config. They should not have the same log level, 
should not share the same database, should not be using the same redis 
instance, or should not be using the same CDN. There can be unsafe things such 
as charging a customer's card, in that case stripe/paypal/whatever all have 
"developer" or "test" API tokens that you should be using in staging. If you're 
worried about sending emails, you should be using a different account or 
something like a mail catcher service. I recommend env vars because that's 
what's easy on Heroku, you don't have to store your config on env vars, but 
I've seen time and time again where having them explicitly linked to your 
RAILS_ENV causes lots of pain.


> Simply as a kind of safety net and fast indicator when I inspect envs within 
> my console.

It's a false sense of safety and actually makes it easier to mess up things. 
For instance I was looking at a friend's app recently and was trying to run 
https://github.com/schneems/derailed_benchmarks (which I wrote). You profile 
your app locally and to do this accurately you need to do it with 
RAILS_ENV=production. We were about to hammer an endpoint when we remembered 
that there were some config (such as billing backend) hard coded into the app. 
So now we can't run benchmarks locally, or if we try we might accidentally 
manipulate production data. 

Even if you're not using performance profiling sometimes bugs only show up in 
RAILS_ENV=production that you need to test locally. If you're checking all your 
config into your app's source that becomes a very dangerous task. If you have 
all your dangerous things decoupled away from RAILS_ENV then it becomes a very 
safe task. 

RAILS_ENV is for behavior, configuration is for secrets. I've seen a huge 
number of cases where tying behavior and configuration together causes many 
many problems, and decoupling them solve many many problems.

Where am I coming from? I work from Heroku and have debugged literally 
thousands of Rails apps over the last 5 years. After writing that article and 
adding a warning to buildpack deploys I saw a significant drop in the number of 
support tickets opened on the platform. At one point is was the largest cause 
of customer tickets. I acknowledge separating behavior (RAILS_ENV) and config 
on non-heroku platforms is harder because the infrastructure for env-vars isn't 
as easy, but the benefits are no different.

-- 
Richard Schneeman
http://schneems.com


On March 2, 2017 at 2:34:38 PM, Dieter Späth ([email protected]) wrote:

To me environment variables make only sense for secret things, config options 
which change often or options you want to be able to change without a 
redeployment.

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

Reply via email to