Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Multidomain Laravel Package

gecche/laravel-multidomain

Run multiple HTTP domains from a single Laravel installation. Each domain gets its own env file, storage path, and database, letting different customers share code but keep separate configuration and data.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. gecche/laravel-multidomain implements hard multi-tenancy at the framework boot layer: one codebase, one deployment, but a distinct .env file, storage subtree, and (typically) database per HTTP host. Tenancy is resolved by intercepting the environment file selection inside a substituted Foundation\Application container, before configuration loads. That places it in a different category from full tenancy platforms (stancl/tenancy, hyn/multi-tenant) — it provides isolation primitives, not tenant lifecycle management. There is no provisioning API, no tenant-aware migration orchestration, no admin plane, and no tenancy-aware Eloquent layer. If the product requirement is "same application, different data per customer," the fit is good. If the requirement is "self-serve tenant onboarding, per-tenant feature segmentation, or row-level tenancy," it is the wrong tool.

Integration feasibility. Feasible, but this is not a drop-in Composer require. It demands two invasive edits: replacing the Laravel Application import in bootstrap/app.php, and replacing Illuminate\Queue\QueueServiceProvider in the provider list. Horizon requires a third substitution in HorizonServiceProvider. These are three touchpoints on framework internals that we must own in code review forever. The tenant registry lives in config/domains.php — a file, not a table — which makes tenant provisioning a deploy-time/config-management operation rather than a runtime one. That is a deliberate design choice and the single most consequential architectural constraint.

Technical risk. Ranked by impact:

  1. Silent cross-tenant fallback. Documented behavior: if no domain-specific .env is found, the standard .env is used. A misconfigured or newly pointed hostname will happily serve against the default database. This is a data-isolation hazard, not a bug, and it must be neutralized with an application-level allowlist assertion early in the request lifecycle.
  2. Host detection depends on $_SERVER['SERVER_NAME']. The README explicitly flags environments where this is unset. Behind load balancers, CDNs, or container ingress, SERVER_NAME is frequently unreliable — which is why the package exposes domain_detection_function_web. We must own and test that closure per environment.
  3. Framework-internals coupling. Overriding the container and queue provider means Laravel major upgrades can break us in non-obvious ways. The maintainer has tracked majors well through 13.x, but that is a single-person dependency chain.
  4. config:cache is per-domain. php artisan config:cache --domain=site1.com writes config-site1_com.php. Miss one domain in the deploy pipeline and it runs on a stale or default cache — a class of failure that is invisible until a customer reports wrong data.

Key questions. (a) What is the support model and response SLA from the maintainer — is there a funded fork or vendor backstop for security patches? (b) Is there a validated path for Laravel Octane / long-running workers, where per-request container boot semantics change? (c) Where do per-tenant secrets live in our target infrastructure — this design assumes env files on disk, which conflicts with 12-factor config injected as process environment. (d) Does the tenant registry need to be dynamic (e.g., customer-defined subdomains) within the next 18 months? If yes, this package alone will not carry us. (e) How many tenants do we expect at peak — the operational model costs one queue worker per domain.

Integration Approach

Stack fit. Strong fit for a Laravel 10–13 monolith deployed as a single artifact per region, with a handful to a few dozen brand-level or customer-level domains, each needing isolated data and public storage. Poor fit for serverless/immutable-image deployments where writing .env.<domain> files at runtime is not possible, and poor fit for high-tenant-count (100+) self-serve SaaS.

Migration path. Two viable entry points:

  • From single-tenant: cleanest. Install, pilot one secondary domain, validate env/storage/DB isolation, then promote remaining domains. No data model rewrite required, since isolation is at the connection level.
  • From another tenancy package: treat as a rewrite of the tenancy layer. config/domains.php is a static registry and will not map onto a database-backed tenant table without us building a synchronizer. Budget for it explicitly; do not assume a swap.

Compatibility. The version matrix tracks Laravel majors 1:1 from 10.x onward, and older 5.x/6.x-era releases are functionally equivalent — good signal that the maintainer keeps parity with framework releases. Constraints to verify in a spike: Horizon (supported, with an extra substitution), storage:link (explicitly not supported per-domain — symlinks must be created manually and wired via APP_PUBLIC_STORAGE in each .env), Octane (undocumented), and any other package that also overrides bootstrap/app.php or the provider list.

Sequencing. Four gates, each a hard stop:

  1. Spike (1–2 weeks). Stand up two domains locally and in a staging environment matching production ingress. Confirm host detection works behind our actual load balancer/CDN.
  2. Isolation guardrail. Implement and test pre-request validation that rejects unknown hosts and fails closed rather than falling through to the default .env.
  3. Deploy pipeline. Extend CI/CD to loop config:cache --domain=…, generate/mount per-domain env files from our secret store, create per-domain storage symlinks, and run per-domain migrations. This is the bulk of the work and is ours, not the package's.
  4. Queue and scheduler. Generate supervisor config per domain; separate queue names per tenant as the README recommends, otherwise workers cross-process jobs.

Operational Impact

Maintenance. Moderate-to-high and permanent. Every Laravel major upgrade becomes a package-compatibility gate plus a review of three framework-internal substitutions. The package is MIT with a single maintainer and no dependents to reveal failure patterns — we should assume we may need to fork and patch, and staff accordingly. The code surface is small, which makes forking tractable.

Support. Community-supported, no vendor. Internal ownership must be assigned to a named engineer with Laravel-internals fluency. Budget a standing allocation for upgrade work rather than treating this as a one-off integration.

Scaling. Two axes behave very differently. Per-tenant load scales horizontally without issue. Tenant count scales linearly in operational cost: one env file, one storage tree, one config cache, one set of migrations, and one queue worker process per domain. At 10–20 domains this is boring infrastructure. At 100+ it becomes a process-management and deploy-time problem that will push us toward a database-backed tenancy model. Set a threshold now — e.g., revisit at 25 domains — and write it into the decision record.

Failure modes. Ranked for on-call:

  • Wrong-tenant reads/writes via the default .env fallback — highest severity; mitigate with the allowlist assertion and a smoke test that hits each domain post-deploy.
  • Stale config cache for a domain omitted from the deploy loop — silent, hard to diagnose; mitigate by asserting config-site*.php count matches domain:list in the pipeline.
  • Host detection drift after a networking change (new WAF, proxy, or CDN rewrite) — sudden all-tenants-on-default behavior; alert on tenant-resolution fallbacks.
  • Missing storage symlink for a newly added domain — broken public assets only, low severity, easily caught.
  • Queue misrouting if queue names are not tenant-scoped — jobs processed under the wrong connection; enforce naming convention in config.

Ramp-up. A senior Laravel engineer can ship the two-domain pilot in about a week. Team-wide fluency — the deploy pipeline, the queue topology, the fallback guardrails — is more like three to four weeks of elapsed work, most of it in CI/CD and observability rather than in the package itself. Expect the package integration to be the small part of the effort; the operational scaffolding around it is the real cost.

Recommendation. Conditional go, pending a timeboxed spike that proves host detection behind our production ingress and demonstrates a fail-closed isolation guardrail. The package is well-matched, honest about its constraints, and small enough to fork — but it supplies isolation mechanics, not tenancy operations. Approve only with a named owner, a documented tenant-count threshold for revisiting, and deploy-pipeline work scoped as a first-class deliverable.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route