Ruby 3.1

3.1 released 25 December 2021, latest 3.1.7.

Ruby 3.1 reached end of life on 26 March 2025.

What changed

Ruby 3.1 added the experimental YJIT just-in-time compiler as an alternative execution engine, introduced more detailed error-location highlighting through the error_highlight default gem, and bundled the debug gem for modern Ruby debugging. The language also added shorthand hash-value syntax, allowing a local variable to be used as both a hash key and value with {name:}, and added Class#subclasses for enumerating direct subclasses. It updated bundled and default components, including RubyGems, Bundler, IRB, RDoc, Psych, and OpenSSL-related integration, so applications can encounter behavioral changes outside their own source code when moving from Ruby 3.0.

What staying costs

Ruby 3.1 has reached end of life, so upstream no longer provides maintenance or security fixes for the interpreter and its maintained components. Newly discovered vulnerabilities, correctness defects, and compatibility problems must be accepted, mitigated locally, or resolved by upgrading. Dependency maintainers increasingly test and publish against newer Ruby lines, which can leave a 3.1 application unable to adopt current gem versions or force it to retain older dependency versions with their own security and maintenance exposure. Native extensions, operating-system toolchains, OpenSSL libraries, and deployment images are particular compatibility risks because they can stop building or running cleanly even when application code has not changed. Remaining on 3.1 also preserves older runtime behavior and limits access to later interpreter, language, debugging, and performance improvements.

What to do

Plan an upgrade to a currently supported Ruby line, selecting the target based on framework, gem, operating-system, and deployment-platform compatibility rather than treating the Ruby version change in isolation. First, make the 3.1 build reproducible by recording the exact Ruby patch level, Bundler version, lockfile, native build dependencies, environment variables, and production image or host configuration. Run the full test suite, static checks, and representative background-job and command-line workloads on the target Ruby; treat warnings, changed exception output, encoding behavior, and dependency resolution changes as migration findings. Update gems in controlled groups, prioritize dependencies with native extensions or Ruby-version constraints, and review changelogs for the framework, database drivers, web server, background-job system, and observability agents. Test deployment builds and production-like workloads, compare boot time, memory use, and latency, and validate any JIT configuration separately from functional compatibility. Keep rollback artifacts available, then retire the 3.1 runtime and its associated build images once the newer runtime is operating reliably.

We can tell you what moving off Ruby 3.1 involves.

What it takes to move off Ruby 3.1 depends on what you built on it — the version you are on, how much depends on it, and how much of the work is mechanical. Leave your email with this version and we can tell you what that looks like for you.

Not sure yet? Get my plan