What Is New in Ruby 3.0
Ruby 3.0 delivers on the Ruby 3x3 performance goal and introduces major new features focused on concurrency, typing, and overall language evolution.
| Category | Key Changes |
|---|---|
| Performance | MJIT improvements, Ruby 3x3 performance target achieved |
| Concurrency | Ractor and Fiber Scheduler for parallel execution |
| Static Analysis | RBS for type definitions, TypeProf for type inference |
| New Features | Right-hand assignment, Find pattern, Endless method definition |
| Changes & Removals | Keyword arguments separation, Deprecation of $SAFE and taint mechanics |
How does Ruby 3.0 improve performance?
The big story is that Ruby 3.0 meets the Ruby 3x3 target, making it three times faster than Ruby 2.0 in many benchmarks. The MJIT compiler got significant optimizations, though it's still considered experimental. In practice, you'll see the most substantial gains on long-running, CPU-intensive applications.
What new concurrency models are introduced?
Ractor is the headline feature, providing an Actor-model abstraction for true parallel execution without a global lock. It's a game-changer for CPU-bound tasks. The new Fiber Scheduler interface also allows for lightweight, non-blocking I/O operations, making it easier to write highly concurrent network applications.
This matters because it moves Ruby beyond the GIL for specific use cases. You can now spin up multiple Ractors to handle workloads in parallel, something that was previously impossible.
How does static typing work in Ruby 3.0?
Ruby 3.0 introduces RBS, a language to describe the structure of Ruby programs, and TypeProf, a tool that generates RBS prototypes from actual code. This isn't compile-time type checking but a system for static analysis that integrates with editors and other tools.
You write type definitions in .rbs files. This helps catch type-related bugs earlier and improves developer tooling like autocompletion and documentation generation.
What syntactic sugar was added?
Several convenient syntax additions landed. Right-hand assignment lets you assign to a variable before using it in an expression. Endless method definitions provide a concise one-liner syntax. The Find pattern is a new addition to pattern matching for grabbing the first matching element in an array.
# Right-hand assignment
42 => result
# Endless method definition
def square(x) = x * x
# Find pattern
case ["a", 1, "b", 2]
in [*, String => a, Integer => n, *]
[a, n] #=> ["a", 1]
end
What breaking changes should I watch for?
The most significant change is the separation of keyword arguments from positional arguments. In Ruby 3.0, keyword arguments are completely separated and will not be auto-converted from a final Hash positional argument. This will break code that relied on the old behavior.
Additionally, the $SAFE feature and taint mechanics, which were already deprecated, have been completely removed. You'll need to remove any related code from your codebase.
FAQ
Is the MJIT compiler ready for production use?
It's still labeled as experimental. While it shows great performance improvements, especially on workloads like Optcarrot, you should benchmark it for your specific application before relying on it in production.
How stable is the Ractor API?
Ractor is a new and powerful feature, but its API is still evolving. It's best suited for experimenting and for specific, isolated parallel tasks rather than as the foundation for a whole application just yet.
Do I have to use RBS and static types?
No, using RBS is entirely optional. Ruby remains a dynamically typed language. RBS is there to assist with development tools and larger codebases where explicit interfaces are beneficial.
What's the easiest way to upgrade from Ruby 2.7?
Address keyword argument warnings first. Ruby 2.7 provided a warning mode for the new keyword argument separation. Fixing those warnings is the primary step to ensure a smooth upgrade to Ruby 3.0.
Are there any new garbage collection features?
Yes, the garbage collector has been tuned. A major change is that the heap is now defragmented by compaction, which can help reduce memory usage. This happens automatically, but there are also new APIs to manually trigger it.