My Thoughts on Ruby 4.0.0: Ruby Box, ZJIT, and More
The wait is over! Ruby 4.0.0 has officially been released. 🎉
I've been following the development of this version closely, and naruse just dropped the announcement on Christmas day. It introduces some massive changes like "Ruby Box" and "ZJIT" that I think are going to fundamentally change how we build and deploy Ruby applications.
Here is my breakdown of the release and what I find most exciting.
Ruby Box: True Isolation?
The standout feature for me is Ruby Box. It's currently experimental, but the implications are huge. It basically allows you to create isolated containers within a Ruby process.
You enable it with RUBY_BOX=1, and it gives you a Ruby::Box class. Code loaded inside a box is completely isolated—monkey patches, global variables, and even class definitions don't leak out.
I can already see a few killer use cases for this in my own projects:
- Safer Testing: I can run test cases that require heavy monkey-patching without worrying about polluting the global state for other tests.
- Blue-Green Deployment: Running different versions of an app or dependency logic in parallel within the same process? That sounds wild, but it might just work for safer rollouts.
It feels like we're getting a standardized way to do what gems like sandbox tried to do years ago, but built right into the core language.
ZJIT: The Next Generation JIT
We have YJIT, which has been fantastic, but now we have ZJIT. It's a new method-based JIT compiler built in Rust.
Why another one? The goal seems to be raising the performance ceiling even higher than YJIT by handling bigger compilation units. It's not faster than YJIT yet (the core team admits this), but it's designed to be more accessible for contributors.
I probably won't deploy this to production just yet, but I'm definitely going to enable --zjit locally to play around with it.
Ractor is Growing Up
I remember when Ractor was introduced in 3.0. It was promising but rough. In 4.0, it feels like it's finally growing up.
They've added a Ractor::Port class which makes message passing much more intuitive compared to the old yield/take mechanism.
port1 = Ractor::Port.new
port2 = Ractor::Port.new
Ractor.new port1, port2 do |p1, p2|
p1 << 1 # Sending is much cleaner now!
p2 << 11
end
The team is aiming to remove the "experimental" status next year, and honestly, with these performance improvements and the reduction in global lock contention, we might finally see true parallelism become standard in Ruby web servers.
Other Cool Tidbits
There are a ton of smaller language changes, but a few caught my eye:
-
Logical operators at start of line: Finally! We can write multiline conditions like this without syntax errors:
if condition1 && condition2 # ... endThis has bugged me for years.
-
Array#rfind: A more efficient way to find the last element matching a condition. Small, but I'll use it. -
Better Error Highlighting:
ArgumentErrornow shows snippets for both the caller and the callee. Debugging method signature mismatches just got way easier.
Final Thoughts
Ruby 4.0.0 feels like a "hardening" release in many ways. It's taking the experimental ideas from 3.x (Ractors, JITs) and giving them solid, usable interfaces.
I'm particularly excited to experiment with Ruby Box. Expect a follow-up post once I've had a chance to build something weird with it.
Merry Christmas and Happy Hacking! 🎄💎