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
TracePointAPI 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.setupFor gem authors, Zeitwerk offers a helper:
1require "zeitwerk"
2
3loader = Zeitwerk::Loader.for_gem
4loader.setup
5
6module MyGem
7 include MyLogger
8endOnce setup is done, constants are ready to be referenced without manual requires.
How Zeitwerk Works
Zeitwerk leverages Ruby’s constant resolution flow:
Module.nestingModule.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
4endThis 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 = :classicLinks
- 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.