I run a self hosted Discourse install (2026.5.0-latest). Today I tried to turn YJIT on. I added "templates/enable-ruby-yjit.yml" to containers/app.yml and rebuilt the app.
After the rebuild was done, something interesting happened. Inside the Docker container, I ran env | grep RUBY_YJIT_ENABLE and got RUBY_YJIT_ENABLE=1. So far so good. But then I ran sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION' … I got:
So YJIT was not enabled, despite adding the enable-ruby-yjit.yml template. Then, when I ran sudo -u discourse RAILS_ENV=production bundle exec rails runner 'puts "GlobalSetting.yjit_enabled=#{GlobalSetting.yjit_enabled}"' I got GlobalSetting.yjit_enabled= — a nil value!
Anyway, after futzing around with it a bit more, I finally got YJIT enabled by adding the following to containers/app.yml:
env:
DISCOURSE_YJIT_ENABLED: true
I’m sure there’s a bug somewhere (GlobalSetting.yjit_enabledshouldn’t ever return nil) but setting the env variable worked, and I hope someone Googling for this will find this topic.
Looking at the presence of an env var doesn’t tell you anything about whether Ruby is currently running with YJIT enabled. In this particular case, the env var is set but something else was clobbering the variable Rails uses to enable (or disable) YJIT on startup! (Or at least … that’s my suspicion).
There’s no other explanation for why GlobalSetting.yjit_enabled= returns nil, even on a new Rails instance. There’s also no reason why YJIT should be turned off on a new Rails instance.
After adding the DISCOURSE_YJIT_ENABLED env var to my containers/app.yml,
This is wrong. At the Ruby level, the ENV var is one of the official toggles, see the Ruby official documentation about this here
This is wrong as DISCOURSE_YJIT_ENABLED only feeds GlobalSetting.yjit_enabled → config.yjit in config/application.rb. Rails uses that to enable YJIT if it isn’t already on. It does not disable an already-enabled YJIT. So when the env var is set, DISCOURSE_YJIT_ENABLED has nothing to do.
To further prove my point I wrote a plugin that returns if YJIT is enabled on my web process:
Huh! So you’re saying we can reliably use the env var to detect if YJIT is enabled! I didn’t know that; thank you for the link to the Ruby documentation.
I’m a little confused about something though. How is it possible that env | grep RUBY_YJIT_ENABLE returns RUBY_YJIT_ENABLE=1, but a new Rails instance in the same container when asked to print #{RubyVM::YJIT.enabled?} outputs false? Shouldn’t it output true since — as you’ve mentioned, this env var works at the Ruby level?
You’re probably really busy and this shouldn’t matter, so no need to answer. I should be able to figure it out on my own server. Could I have your plugin, by any chance? I want a way to be sure that my Discourse server is running on a Ruby with YJIT enabled.
I’ll mark your response as a solution after I’ve replicated.
sudo -u discourse scrubs the env. Using the -E flag brings the normal env along, and in that case sudo -E -u discourse RAILS_ENV=production bundle exec rails runner 'puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"; puts RUBY_DESCRIPTION' returns
I apologise for wasting your time, and have marked your response as the solution. Sorry about this. Thank you for investigating and taking the time to respond.