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.
What is Zeitwerk?
Zeitwerk is a code loader gem developed by Xavier Noria. It provides:
- Autoloading of constants
- Eager loading for production
- Reloading in development
- Thread safety by design
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.
Why Zeitwerk?
The motivation behind Zeitwerk was to keep code DRY and remove the need for brittle require
calls. It also improves reliability by:
- Respecting Ruby's constant resolution rules
- Using the
TracePoint
API to manage nested modules - Reducing confusion with explicit autoload paths
Zeitwerk is available as a standalone gem, so you can also use it in non-Rails Ruby projects.
Using Zeitwerk in a Non-Rails Project
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.
How Zeitwerk Works
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:
- File must be named after the class
- Must reside in an autoload path
Zeitwerk Mode and TracePoint
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.
Reverting to classic loader in Rails
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
Links
- Relevant Commit
- Zeitwerk-Rails integration
- Rails Documentation for Autoloading and Reloading Constants (Zeitwerk Mode)
- Zeitwerk GitHub Repo
Summary
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.