Deployment
🚀 Deployment
🌍 Environments
Rails has always run in one of three environments — development, test (both used constantly throughout this course without being named explicitly), and production — each with its own config file under config/environments/. force_ssl is a direct callback to the completed HTTPS/TLS course: one config line gets an entire app the redirect-to-HTTPS and HSTS-header behavior that course covered manually with nginx.
🔑 Credentials — Rails' Built-In Secrets Management
rails credentials:edit opens an editor on an encrypted config/credentials.yml.enc file, decrypted using a config/master.key that's git-ignored by default and provided to the production server separately (as an environment variable, or a mounted secret). This is Rails' equivalent of the .env-file approach node2-6 covered for Express — except the secrets themselves are encrypted and safe to commit, and only the one small key needs careful handling, rather than an entire plaintext file of values.
📦 Asset Precompilation
The Stimulus controllers and CSS from rails2-7 are development-friendly source files — in production they need to be bundled, minified, and fingerprinted (a content hash added to each filename, so browsers can cache them aggressively and safely bust that cache the moment a file changes). assets:precompile does all of this in one step, producing the static files actually served in production. This is one more thing Express's plain express.static (covered in express1-5) never needed — Express serves whatever files are already sitting in a directory, with no separate build step assumed by the framework itself.
🗄️ Production Database Configuration
Rather than hardcoding host/username/password, production reads a single DATABASE_URL — the same connection-string shape covered for raw mysql2 pooling in node2-5 — supplied by whatever hosts the database. pool caps how many concurrent connections each server process opens, matched to the app server's thread count so connections aren't wasted sitting idle or, worse, exhausted under load.
🟣 Deploying to Heroku
Heroku reads the Procfile to know how to run the app: a web process serving requests, and a release process that runs once per deploy, before traffic switches over — the natural place for rails db:migrate, so every deploy automatically applies any pending migrations from rails1-5 before the new code goes live.
🐳 Deploying with Docker
Multi-stage builds keep the same principle already established for Node in node3-8: the first stage installs gems and precompiles assets, pulling in build tools and source files the running app doesn't need; the second stage copies over only the finished result, producing a smaller, leaner production image. The Sidekiq worker process from rails2-4 gets its own separate Dockerfile/service in the same deploy, since it needs to run continuously alongside the web process, not inside a single request/response cycle.
📜 Rails Deployment vs Express Deployment
Rails vs Express (express2-8)
| Concern | Express | Rails |
|---|---|---|
| Secrets | .env / dotenv (node2-6) | Encrypted credentials.yml.enc + master.key |
| Static assets | Served as-is, no build step assumed | Precompiled, fingerprinted, minified |
| DB migrations on deploy | Run manually or in a custom CI step | Procfile release phase (Heroku), or explicit step |
| Process manager | PM2 cluster mode (express2-8) | Puma (threaded/clustered web server) |
| Background workers | Separate Node process (node3-6/node3-8) | Separate Sidekiq process (rails2-4) |
The shapes converge more than they differ: both frameworks end up with a web process, a separate worker process for background jobs, secrets injected via environment/config rather than hardcoded, and a migration step that runs before traffic hits new code. Rails simply bakes several of these decisions (credentials encryption, asset fingerprinting, the release-phase convention) into the framework itself, rather than leaving each project to assemble its own approach.
💻 Coding Challenges
Challenge 1: Production Environment Config
Write the config/environments/production.rb lines that enable eager loading, force SSL redirection, and set the log level to :info. Briefly state, in a comment, why each of the first two would be wrong to enable in development.rb.
Goal: Practice reasoning about which settings genuinely differ between environments, and why.
Challenge 2: A Heroku Procfile
Write a Procfile with a web process running Puma, a release process running pending migrations, and a worker process running Sidekiq (from rails2-4).
Goal: Practice declaring all three process types a real deployed Rails app needs.
Challenge 3: Reading a DATABASE_URL
Write the production: section of config/database.yml reading its connection info entirely from ENV["DATABASE_URL"], with a connection pool size read from an RAILS_MAX_THREADS environment variable, defaulting to 5 if unset.
Goal: Practice configuring the database from environment variables rather than hardcoded values.
Nothing in this chapter is really new engineering — it's making sure everything already built across this course (auth cookies needing HTTPS, Sidekiq needing its own process, migrations needing to run before new code serves traffic) actually holds up outside a development laptop. A feature that only works in development isn't finished; this chapter is what "finished" actually means.
🎓 Course Complete
This closes out Ruby on Rails Intermediate/Advanced — and with it, the full Ruby on Rails track (16 chapters across both courses), built on top of the full 16-chapter Ruby language track. From rails1-1's first rails new to a tested, authorized, real-time, deployed API: convention over configuration, followed all the way through.