The pre-launch Rails health checklist

Rob Bazinet, founder of RailsHealth.

By Rob Bazinet

· 6 min read

“Pre-launch” means different things depending on what’s about to happen. The check you run the night before a public launch is different from the one you run before handing the code to a client, which is different from the one you run before a due-diligence call with an acquirer, which is different from the one you run on day one of being the new on-call.

This is four versions of the same checklist, scoped to each of those situations. Use the one you need.

Cut 1: the “going to production for the first time” version

This is the one most people think of when they say “pre-launch.” First real users, real money, real consequences if it breaks.

Security

  • config.force_ssl = true in config/environments/production.rb. Confirm with curl.
  • Production secrets are not in the repo. git log --all -p config/master.key, git log --all -p config/credentials.yml.enc — verify these were created locally, never committed in a form you didn’t intend.
  • bundle exec bundler-audit check --update is clean, or each finding has a documented disposition.
  • bundle exec brakeman is clean on the categories you decided are blocking (SQL injection, mass assignment, open redirects, command injection). Don’t try for a zero-warning Brakeman report on launch day.
  • Rate limiting is on at least the login, signup, and password-reset endpoints. rack-attack or equivalent.
  • Strong parameters everywhere that takes user input. If a controller has params.permit!, you’d better have written the code yourself and know why.
  • Any third-party API keys are in env vars or encrypted credentials, not source.
  • CSRF is on. (It is, by default. Confirm anyway.)

Reliability

  • An error tracker is wired up and you’ve fired a test error from production to confirm it actually reports.
  • Logs go somewhere you can read. STDOUT is fine if a log aggregator picks them up; “the disk on the production box” is not fine.
  • The deploy has a health check endpoint (/up in Rails 7.1+; roll your own otherwise) and your load balancer or platform uses it.
  • A database backup is configured and you have personally restored from one. Not theoretically — actually.
  • You know what happens when the database falls over. The answer can be “the app 500s and we get paged”; it can’t be “I don’t know.”

Performance, but only the cheapest version

  • N+1s on the home page and the most-trafficked endpoints. bullet will tell you. Fix the obvious ones.
  • Foreign keys are indexed. (See the audit guide — this is one of the most common omissions and one of the cheapest fixes.)
  • The slowest query in any request path is under 100ms in production. If you can’t measure that, get an APM first.

That’s the minimum. Don’t let “we should also…” push the launch by another month. Ship.

Cut 2: the “handing off to a client” version

You built this for a client. They’re taking it over. You want to leave it in a state where a competent Rails developer can pick it up tomorrow and not have a panic attack.

  • A README.md that explains how to get the app running on a fresh laptop. Test it on a fresh laptop.
  • The development setup uses standard Rails conventions or there is documentation explaining the deviations. No surprise build steps.
  • bin/setup actually works. If it doesn’t, fix it.
  • Database seeds, or a db:reset task, that produces a usable development environment in under 60 seconds.
  • A list of all third-party services in use, with what each one does and where the keys live. This goes in README.md or docs/services.md. The client should be able to read this and know what they’re paying for.
  • Documented backup procedure.
  • Documented deploy procedure.
  • An admin user the client knows the password for, and a documented way to create more.
  • A note about the test suite: how to run it, what the coverage is, what’s tested and what isn’t. Be honest. If e-commerce flows are tested and the admin panel isn’t, say so.
  • No personal access tokens, no personal API keys, no credentials in your name. Everything is the client’s now.

The check I run on this one is harsher than the production launch check, because in the production launch the team that built the app still owns it. In the handoff, the team that owns it tomorrow is reading the codebase cold.

Cut 3: the “due diligence for acquisition” version

Someone is buying the company, or the codebase, or a license. There’s a technical diligence call coming up. They’ll have someone competent on their side, and they’ll ask sharp questions.

What they will look at:

  • Open-source license compliance. Are there any GPL gems in use that should worry them? AGPL especially. Check bundle exec license_finder or equivalent. Don’t let this be a surprise.
  • Patent / IP issues. Less common, but: any gem with a non-standard license, anything custom-licensed, anything where the IP story is “we forked it and we’re not really upstream.”
  • Security posture. They’ll ask about CVE-tracked dependencies, secrets handling, auth implementation, and how you respond to vulnerability reports. Have a one-page answer for each.
  • Operational maturity. They’ll ask how deploys happen, how incidents are handled, what the SLA is, what the on-call rotation looks like. “We don’t have one” is a fine answer for a small company; “I don’t know” is not.
  • Test coverage. Not the percentage — the answer to “what happens if you change something in the order flow and the tests pass.” If “we feel confident shipping,” you’re fine. If you wince, they’ll see the wince.

The acquisition cut is mostly about having coherent answers to questions you can predict. Most teams know less about their own codebase than they think they do; an hour of preparation here makes a difference.

Cut 4: the “you’re now on call for this” version

You inherited the on-call rotation. The app exists, it’s in production, and at 3am tomorrow something will go wrong and your phone will ring.

  • You can SSH into / kubectl exec / fly ssh console / whatever the app’s platform supports, and you’ve done it once successfully.
  • You can read production logs from your laptop without leaving your house. Right now. Try it.
  • You know how to roll back a deploy. You know how to roll back a database migration. You know how to disable a feature flag.
  • You have the runbook, or there is no runbook and you’ve made a note that the first action item is to write one.
  • You know what each scheduled job does. (bin/jobs, Sidekiq, cron, whatever the team is using.) You don’t need to be able to debug them, but you need to know what they’re called and roughly when they run.
  • You know which page is “the canary” — the first one that breaks when something is going wrong. If the team doesn’t have one, the home page is fine.
  • You can contact a human on the team who knew this codebase before you. If they’re gone, you’re operating without a net.

What of this can RailsHealth automate

The security cut and the database/index cut are almost entirely mechanical, and they’re what RailsHealth runs every week. So is the version-currency check (is Rails supported, is Ruby supported) and the deploy-readiness check (does this app have a Dockerfile, a health check endpoint, an error tracker).

The handoff and acquisition and on-call cuts are mostly process and documentation questions, and process is on you. The product doesn’t pretend it can do those parts — those parts depend on knowing your team and your customer.

The list is the list. The question is just whether you find each item on it by hand, every quarter, or once.

Try RailsHealth

14-day trial. No credit card to start. Read-only GitHub access — we never run your code.

Connect your GitHub repo

Related guides

Feedback