torikago
torikago is a gem for introducing per-module runtime boundaries to Rails modular monoliths. It aims to strengthen runtime isolation with Ruby::Box, in addition to the structural boundaries you can already get from tools like packwerk and Rails::Engine.
With torikago, module-to-module calls are funneled through Torikago::Gateway.call(...), and each module declares which Package APIs it exposes and which modules may call them. This makes it easier to prevent unintended cross-module references at runtime.

Configuration example
Register modules from your Rails app:
Torikago.configure do |config|
config.register(
:foo,
root: Rails.root.join("modules/foo"),
entrypoint: "app/package_api", # optional
setup: "config/box_setup.rb", # optional
gemfile: "Gemfile" # optional
)
end
The main config.register options are:
root- the module root directory
entrypoint- the directory, or file under that directory, used to discover public APIs
- defaults to
app/package_api
setup- a setup hook loaded before Box boot completes
- useful for monkey patches or Box-specific initialization
gemfile- a Gemfile used to resolve Box-specific gem require paths
- during Box cold boot, the resolved require paths are prepended to that Box's
load_path - this is intended to let module code
requiremodule-local gem versions without relying on main-box gem activation
On the module side, declare the Package APIs you expose and which modules may call them:
exports:
Foo::ListProductsQuery:
allowed_callers:
- baz
Calls from the module itself and from the main box are allowed implicitly. allowed_callers only restricts calls coming from other modules.
Call a Package API by class name:
Torikago::Gateway.call("Foo::ListProductsQuery")
# with arguments
Torikago::Gateway.call("Bar::SubmitOrderCommand", title: "Book")
Torikago::Gateway.call(...) resolves the target module from the class name, checks the exported Package API declaration for that module, and then runs new.call(...) inside the target Box.
Example app
A minimal Rails example app lives in example/rails-modular-monolith/.
Usage
Run gem tests
bundle exec rake test
Run example app tests
cd example/rails-modular-monolith
RUBY_BOX=1 bundle exec rails test
Start the example app
cd example/rails-modular-monolith
RUBY_BOX=1 bundle exec rails s
RUBY_BOX=1 is required to actually enable Ruby::Box.
CLI
Use the CLI via exe/torikago:
bundle exec ruby exe/torikago --help
Main commands:
torikago init- interactively generate
package_api.ymlfiles andconfig/initializers/torikago.rb
- interactively generate
torikago check- validate
Gateway.callusage against manifests
- validate
torikago update-package-api [BOX]- regenerate
package_api.ymlfrom the configured entrypoint
- regenerate
torikago check scans Torikago::Gateway.call("...") usage and verifies:
- the class is declared in a manifest
- the caller module is included in
allowed_callers - the manifest entry has a matching implementation file
About RUBY_BOX=1 and boot
The current example app includes a few practical boot workarounds to keep Rails startup stable under RUBY_BOX=1:
- disable Bundler plugins
- load
tmpdirearly - avoid
Bundler.require(*Rails.groups)underRUBY_BOX=1and require the needed gems explicitly
These are pragmatic workarounds for the current example app, not a finalized long-term contract for torikago.
Current limitations
- Initial Box boot is slow
- cold boot can take several seconds
Ruby::Boxitself is still experimental- segfaults and instability can happen
- Some gems do not cooperate well with this model
- especially global-effect gems that influence the whole VM
- Full
Rails::Engineconfinement is still difficult to do cleanly
Common errors:
Torikago::DependencyError- an unauthorized cross-module reference
Torikago::PublicApiError- calling a Package API that is not declared in the manifest
Torikago::GemfileOverrideError- failure while resolving or activating a Box-specific Gemfile override
So, at the moment, torikago is better understood as an implementation exploring how far runtime boundaries in a modular monolith can be pushed, rather than a fully production-ready finished product.