bchalier/laravel-modules
Laravel Modules lets you split a Laravel application into self-contained modules, each with its own routes, views, migrations, config, and service providers. It provides the tooling and bootstrapping needed to register, organize, and manage modular codebases more cleanly.
Architecture fit. The package's design premise is sound and Laravel-idiomatic. A "module" here is not a new runtime abstraction — it is a namespaced slice of the application with its own service provider, route files, config, and migrations, registered through Laravel's existing bootstrapping lifecycle. That is the correct primitive for a modular monolith: it means an exit strategy exists by construction, because the modules are still ordinary Laravel code. For teams reasoning in bounded contexts (orders, billing, catalog) this maps cleanly onto how Laravel already thinks about packages.
Integration feasibility. The integration surface appears small — a Composer dependency, a directory convention, and automatic discovery/registration. That is attractive on paper but also where the risk concentrates: "automatic discovery" is magic, and magic is what breaks across framework majors. Concretely, a 2021-era package that participates in the bootstrapping lifecycle is likely to make assumptions that Laravel 11+ invalidated — the removal of app/Http/Kernel.php and app/Console/Kernel.php, the move to bootstrap/app.php, and the shift to Application::configure(). Any of these can make module discovery, route loading, or middleware registration silently no-op. Verification on the actual target Laravel version is a gating step, not a formality.
Technical risk. High, on non-technical grounds before technical ones:
config:cache and route:cache are common production optimizations and are a classic break point for filesystem-scanning registrars.The countervailing factor is that the codebase is small and the concepts are simple. This is forkable and patchable by a mid-level engineer in days, not weeks. The risk is not "this is unfixable," it's "we will own it and we should say so out loud."
Key questions. These need answers before any adoption decision:
illuminate/support / laravel/framework constraint in composer.json, and is there a CI matrix proving it?Stack fit. Appropriate for a medium-to-large Laravel monolith — call it three or more distinct business domains — where the team wants enforced separation without adopting a full DDD apparatus. It is a poor fit if the application is already organized into Composer path-repositories, already uses nwidart/laravel-modules (the dominant incumbent, orders of magnitude more adopted and actively maintained), or is small enough that app/Domain/* namespacing with plain providers would do. Do not introduce this into a codebase that has no existing modularity problem; the package is a convention, not a solution.
Migration path. Incremental and reversible. Start with a single domain extracted into one module: move routes, controllers, models, config, and migrations, then run the full lifecycle — HTTP route resolution, console commands, queued jobs, scheduled tasks, config publishing, and migration execution. Because modules remain ordinary Laravel code, an exit ramp exists: deregister the package and list the module providers explicitly. Preserve that exit ramp by keeping module boundaries expressed as service providers rather than as package-specific configuration.
Compatibility. Treat version compatibility as a binary gate. If composer.json pins to a Laravel major we no longer run, the decision becomes fork-and-patch versus abandon — not "try it and see." If the constraint is loose but untested, assume breakage until a spike proves otherwise.
Sequencing.
config:cache and route:cache.nwidart/laravel-modules or a ~200-line in-house registrar using Illuminate\Support\ServiceProvider plus a directory scan.Maintenance. Assume full ownership from day one. An unmaintained dependency is not a dependency, it is vendored code you have not copied yet. Budget explicitly for it: fork into an internal namespace, add CI against each Laravel major you support, and assign an owner. The package is small enough that this is measured in days per year — but it is recurring, and it must appear in the upgrade runbook alongside composer update.
Support. No vendor, negligible community, effectively no StackOverflow footprint. Every question that would normally be answered by the internet becomes an internal debugging session. Mitigate with internal documentation: module anatomy, the discovery mechanism, common failure signatures, and how to debug a module that "isn't loading."
Scaling. Runtime cost is negligible — provider registration is a rounding error against request handling. The real scaling concern is organizational: the package provides mechanism but no governance. It will not stop module A from reaching into module B's Eloquent models. Boundary enforcement — no cross-module model imports, communicate via events or explicit service interfaces, shared contracts in a small common module — has to be a reviewed convention or the modularity decays into a namespaced ball of mud within a year.
Failure modes. Ranked by likelihood and pain:
config:cache / route:cache in production altering discovery behavior; works locally, fails deployed. Test the cached path in CI.Ramp-up. Low for anyone who has written a Laravel package — service providers, config publishing, and namespaced autoloading are core Laravel skills. Realistic ramp is a half-day of reading plus one paired extraction. The cost is not learning the package; it is learning our conventions on top of it, and that cost is identical whether we use this package, a competitor, or a hand-rolled registrar. That symmetry is the central point: the package is not buying us much beyond a convention and a discovery loop, and the score of 2.1 reflects that honestly. The concept scores well on opportunity (6.85) because modular monolith tooling is genuinely underserved between "nothing" and "full DDD." This specific artifact, however, should be treated as a reference implementation to fork or learn from — not as a dependency to adopt unmodified in a production system we intend to keep for years.
How can I help you explore Laravel packages today?