Skip to content
Allerin, go to homepage

Twelve questions to put to any Rails consultancy, including us

Since 29 July 2026, whether a Rails app is exposed to CVE-2026-66066 depends on a system library inside the container image, not on anything in the Gemfile. Most of what decides an upgrade is like that: visible in an afternoon if you know where to look. These are the twelve places, each with the command or grep that answers it and what we do with each answer.

If you can answer all twelve in an afternoon, you may not need us. If you cannot, the gaps are the scope. Send us your answers and we will tell you what they mean before anyone talks about price.

Sources: FastRuby, 3 August 2026; GHSA-xr9x-r78c-5hrm.

The twelve

  1. 1. Which Rails series and patch level does production run today, and on what date does its security support end?

    Why it matters
    Only 8.0.x and 8.1.x receive security fixes. 7.2.x ended on 9 August 2026, 8.0.x ends on 7 November 2026, and 8.1.x runs to 10 October 2027 (bug fixes end 10 October 2026), so 8.1 is the target of every upgrade scoped this year. 7.0.10 and 7.1.6 were the final releases of their series on 29 October 2025. Rails 8.1 still accepts Ruby 3.2, so a Rails version alone does not tell you whether you are supported.
    The check
    bin/rails runner 'puts Rails.version' in production, then compare with the maintenance page.
    What we do with the answer
    Set the target (8.1.3.1 or later) and count the hops. Everything else on this list is scoped by that number.
  2. 2. What does vips --version print inside your production image, and which activestorage version is in Gemfile.lock?

    Why it matters
    CVE-2026-66066 (CVSS 9.5, advisory dated 29 July 2026) is fixed only in 7.2.3.2, 8.0.5.1 and 8.1.3.1, and the fix needs libvips 8.13 or newer; below that floor the patched gem raises at boot. load_defaults 7.0 is what switched Active Storage to :vips, and Debian bullseye ships libvips 8.10.5 while Ubuntu jammy ships 8.12.1, so the exposure sits in the Dockerfile, not the Gemfile. An app that never raised its defaults may still be on mini_magick and outside the advisory.
    The check
    vips --version in the running image; grep variant_processor config/; bundle list | grep activestorage.
    What we do with the answer
    Treat the image as part of the upgrade: base image at bookworm, noble or trixie level, ruby-vips 2.2.1 or newer, the advisory workarounds while the image catches up.
  3. 3. Which Ruby does production actually boot, and who owns the base image?

    Why it matters
    Ruby 3.2 reached end of life on 1 April 2026, 3.3 is security-only with an expected end of 31 March 2027, and 3.4 and 4.0 are in normal maintenance. Rails 8.1.3.1 still accepts Ruby 3.2.0, so a green Gemfile can hide an unsupported runtime. The image also decides libyaml (unbundled since Ruby 3.2) and libvips; Heroku's default Ruby is 3.3.9.
    The check
    ruby -v inside the production image; cat .ruby-version; the Dockerfile FROM line.
    What we do with the answer
    Ruby bumps between Rails hops, never alongside them: 2.7 to 3.0 before Rails 7.0, 3.1 before 7.2, 3.4 before any move to 4.0.
  4. 4. Which gems on the request path have had no release in 24 months, which are pinned to a git SHA, and which patch Rails internals?

    Why it matters
    Gems block more hops than the framework does. paranoia pinned activerecord below 8.1 in October 2025; data-migrate broke on 7.1 until 9.2.0 despite an open-ended gemspec; 23 gems had undocumented 7.1 incompatibilities. Patches on private API (the ActiveSupport::Deprecation singleton, removed in 7.2) fail with no deprecation to grep for.
    The check
    bundle outdated; grep -n 'git:' Gemfile; grep -rn 'class_eval\|prepend' config/initializers lib.
    What we do with the answer
    A verdict for every gem: upgrade, fork, vendor, replace or delete, with the reason recorded. Vendoring is a bridge, never the destination.
  5. 5. Which of csv, base64, bigdecimal, logger, ostruct, benchmark and cgi does your Gemfile declare explicitly?

    Why it matters
    Ruby 3.4 (25 December 2024) moved csv, base64 and bigdecimal, among others, from default to bundled gems; Ruby 4.0 (25 December 2025) did the same for ostruct, pstore, benchmark, logger, rdoc, win32ole, irb and reline and cut cgi down to cgi/escape. Under Bundler each undeclared require is a bare LoadError, usually raised inside an older gem rather than your code. Ruby 3.3 warns about the 3.4 set and Ruby 3.4 warns about the 4.0 set, which is why both are staging stops.
    The check
    grep -rn "require ['\"]\(csv\|base64\|bigdecimal\|logger\|ostruct\|benchmark\|cgi\)" app lib config Gemfile.lock
    What we do with the answer
    Declare them, then stage Ruby through 3.4 with -W:deprecated on before any 4.0 attempt.
  6. 6. What does config.load_defaults say versus the Rails you run, and how many lines in new_framework_defaults_X_Y.rb are still commented out?

    Why it matters
    The 7.1 template carries 28 settings (cache format, message serializer, column serializer, HTML5 test parser); 7.2 adds enqueue_after_transaction_commit, validate_migration_timestamps and yjit; 8.0 sets to_time_preserves_timezone = :zone, strict_freshness = true and Regexp.timeout = 1; 8.1 adds six more, including raise_on_missing_required_finder_order_columns. The version in your Gemfile and the behavior your app runs are two different numbers, and the gap between them is the real upgrade backlog.
    The check
    grep load_defaults config/application.rb; ls config/initializers/new_framework_defaults*; grep -c '^# ' config/initializers/new_framework_defaults*
    What we do with the answer
    Walk every setting with you and record the production consequence of each before it flips.
  7. 7. Can the app boot on two Gemfiles today, and does CI run the suite on both?

    Why it matters
    Dual boot (next_rails 1.7.0, released 6 August 2026, or Shopify's bootboot) is how an upgrade ships behind a flag instead of behind a code freeze. One Medical moved a 175,000-line, ten-year-old monolith from Rails 5 to 6 to 7 this way with two rollbacks that affected two users. It is table stakes, not a differentiator; if a firm presents it as novel, ask what else they are behind on. If the answer is no, that is the first task, not a finding.
    The check
    ls Gemfile.next Gemfile.next.lock; grep -n 'DEPENDENCIES_NEXT\|BUNDLE_GEMFILE' .github .gitlab-ci.yml .circleci 2>/dev/null
    What we do with the answer
    Both lockfiles in your CI for the whole engagement; each hop its own branch, pull request and deploy.
  8. 8. What is your test coverage on the money, auth and PII paths, including system tests for the JavaScript flows, and is CI green today?

    Why it matters
    The Rails guide says the best protection is good coverage before you start, and coverage is the variance driver every firm names first; the niche leader will not start below roughly 80 percent. Some changes pass tests while meaning something else: 7.2 makes tests honor the configured queue adapter, and 6.1 turned where.not with several conditions into NAND. Those only surface where the paths are covered.
    The check
    simplecov by directory for app/models and the payment, session and account code; the last green CI run's date.
    What we do with the answer
    Where coverage on those paths is thin, characterization tests come first; we will not upgrade blind.
  9. 9. Which asset pipeline are you on (Webpacker, Sprockets, Propshaft), and who owns that migration?

    Why it matters
    Webpacker is retired; Rails 7.0 dropped sprockets-rails from the rails gem's dependencies; 8.0 (7 November 2024) made Propshaft the default for new apps while upgraded apps keep Sprockets with an explicit pin. Practitioners report the front-end move takes more effort than the framework hop, and the Propshaft maintainer says staying on Sprockets is fine, so it is scoped as its own decision.
    The check
    grep -n 'webpacker\|sprockets\|propshaft\|importmap\|jsbundling' Gemfile; ls config/webpack* config/importmap.rb 2>/dev/null
    What we do with the answer
    The front end is its own workstream with its own decision record, never folded into a version hop.
  10. 10. Which Active Job adapter do you run, and is it still in Rails core?

    Why it matters
    Rails 8.1 (22 October 2025) deprecated the built-in sidekiq adapter (sidekiq 7.3.3 or newer ships its own), and the 8.2 edge notes remove it and deprecate the delayed_job, resque, queue_classic, backburner and sneakers adapters. Since 7.2, enqueues defer until after the transaction commits, which changes job timing with no warning in the log. Solid Queue is a product decision, not an upgrade step: it wants MySQL 8 or newer, MariaDB 10.6 or newer or PostgreSQL 9.5 or newer for FOR UPDATE SKIP LOCKED and its own database.
    The check
    grep -rn 'queue_adapter' config/; bundle list | grep -i 'sidekiq\|solid_queue\|good_job\|delayed_job\|resque'
    What we do with the answer
    Upgrade the adapter gem before the hop that deprecates the built-in one; read every perform_later inside a transaction.
  11. 11. How many people can deploy and roll back today, how many minutes does a rollback take, and which migrations in the upgrade branch are irreversible?

    Why it matters
    Rollbacks fail on three things: irreversible migrations, cache entries written in a format the old version cannot read (7.0 and 7.1 each need a two-step deploy), and gem faults seen only in production (a Ruby 4.0.2 rollback to 3.4.9 on latency in April 2026 is the recent public example). strong_migrations 2.8.0 (14 May 2026) guards the first; a named second deployer guards the rest.
    The check
    The deploy runbook, if one exists; the last rollback's date and duration; grep -rn 'def up\|remove_column\|drop_table' db/migrate on the upgrade branch.
    What we do with the answer
    Irreversible migrations ship before the bump with a compatibility window; a cache namespace per version; the rollback rehearsed and timed before the first production deploy.
  12. 12. Which LLM or model calls run inside the request cycle instead of a job, and which of your data leaves your boundary in a prompt?

    Why it matters
    These are the two questions Rails leads ask each other in public. The Ruby side is current: the anthropic gem reached 1.68.0 on 1 September 2026 and the openai gem 0.85.0 on 3 September 2026 (still pre-1.0). The pattern the community converged on is a job, a Turbo broadcast and an Active Record row, not a blocking controller call, and 8.1's Active Job Continuations exist for exactly the long, interruptible work an inference call becomes under a deploy with a thirty-second shutdown. Training and heavy inference still belong in a Python service beside Rails, because the GVL serializes Ruby code inside one process.
    The check
    grep -rn 'Anthropic\|OpenAI\|RubyLLM\|Net::HTTP' app/controllers; the per-tenant spend ceiling, if any.
    What we do with the answer
    Place the calls: inside the request cycle, behind a job, or in a service beside Rails, with a cost ceiling and a kill switch.

The seven questions buyers are told to ask a vendor, answered

Two guides written for buyers of Rails upgrades list the questions to put to any firm. Here are our answers, in the order the guides ask them.

What is your process for gems that are not compatible with the target version?
Each gets a verdict before the first hop: upgrade, fork, vendor, replace or delete, with the reason recorded and reviewed with you. Vendoring is a bridge, never the destination, and a forked gem gets a date by which it is replaced.
Do you upgrade Ruby and Rails in separate steps?
Yes, always, one deploy each, with Ruby bumps between Rails hops. The floors set the order: 2.7 to 3.0 before Rails 7.0, 3.1 before 7.2, 3.4 before any move to 4.0.
Will we work with the same engineers throughout?
Yes. You choose them from full profiles before kickoff and they stay for the whole engagement. Nobody is swapped in behind the scenes.
What happens when the estimate is wrong?
The review scopes each hop before it starts, and each hop is its own deliverable, so a surprise on hop three is visible before hop four is priced. Multi-version paths are scoped and quoted from the review, never estimated up front, for exactly this reason.
Is post-deploy stabilization in scope?
Yes. The engagement ends at a named state, not at the merge: the app on the target version in production, both Gemfiles retired to one, the rollback path exercised, and the per-hop log handed over.
Can we see a past upgrade plan?
Anonymized, under NDA. Our own per-app logs from moving our internal applications to 8.1 are being published as they are written up, and those are the only effort figures we quote.
Why should we upgrade at all?
Because the next advisory will not have a patch for you. CVE-2026-66066 (CVSS 9.5, 29 July 2026) had fixes only for 7.2, 8.0 and 8.1; everything below had to reach 7.2 first. If your app is on 8.1 with a green suite and current gems, the honest answer may be that you do not need us, and we will say so.

Back to Ruby on Rails consulting

Part of Ruby on Rails consulting at Allerin. Founded 2005. Austin, Texas and Navi Mumbai.

Ready to build your product?

84-person senior engineering team, measurable outcomes, fast routes to production.

Procurement team? See our Trust Center →