GAURAV VARMA
Rails 6 introduces Zeitwerk as the new default code loader, replacing the classic autoloader. Zeitwerk provides a modern, thread-safe, and eager-loading-friendly autoloading mechanism.
Zeitwerk is a code loader gem developed by Xavier Noria. It provides:
Unlike the classic autoloader, Zeitwerk doesn’t rely on const_missing
hooks. Instead, it registers autoload paths directly with Ruby using Module.autoload
, aligning more closely with Ruby’s semantics.
The motivation behind Zeitwerk was to keep code DRY and remove the need for brittle require
calls. It also improves reliability by:
TracePoint
API to manage nested modulesZeitwerk is available as a standalone gem, so you can also use it in non-Rails Ruby projects.
Zeitwerk is fully independent and works in plain Ruby apps:
1require "zeitwerk"
2
3loader = Zeitwerk::Loader.new
4loader.push_dir("lib")
5loader.setup
For gem authors, Zeitwerk offers a helper:
1require "zeitwerk"
2
3loader = Zeitwerk::Loader.for_gem
4loader.setup
5
6module MyGem
7 include MyLogger
8end
Once setup is done, constants are ready to be referenced without manual requires.
Zeitwerk leverages Ruby’s constant resolution flow:
Module.nesting
Module.ancestors
It no longer relies on Object.ancestors
, and doesn't override const_missing
.
In the classic loader (Rails < 6), autoloading worked by overriding Module#const_missing
and looking for matching files in ActiveSupport::Dependencies.autoload_paths
. It depended on naming conventions:
Zeitwerk uses Module.autoload
instead. For example:
1loader.push_dir("./lib")
2# Internally does:
3autoload "Automobile", "lib/automobile.rb"
When Zeitwerk sees class Automobile
, it triggers a TracePoint hook. It checks if a directory named automobile/
exists, and sets up autoloads for any files inside, like automobile/engine.rb
.
1class Automobile
2 # TracePoint triggers
3 # Zeitwerk autoloads ./automobile/engine.rb if needed
4end
This design ensures that modules are loaded in a predictable, Ruby-native way.
Rails handles the switch automatically, but apps using non-standard structures may need adjustments. You can temporarily revert to the classic loader with:
1config.autoloader = :classic
Zeitwerk is a significant improvement over the classical Rails code loader. It's thread-safe, efficient, and aligns with Ruby’s native constant loading behavior. With Zeitwerk, Rails apps enjoy cleaner structure, fewer manual require
calls, and a more predictable autoloading experience.
If you're upgrading to Rails 6 or starting fresh, Zeitwerk is already baked in — no extra config needed.