- Is this bundle compatible with Laravel, or is it strictly for Symfony?
- This bundle is designed exclusively for Symfony. While it shares conceptual similarities with Laravel’s stancl/tenancy (e.g., tenant resolvers, zero-boilerplate philosophy), it integrates deeply with Symfony’s kernel, Doctrine, Messenger, and other core components. If you’re using Laravel, stancl/tenancy remains the better fit.
- How do I install and configure the bundle for a new Symfony project?
- Install via Composer with `composer require danplaton4/tenancy-bundle`, then run `php bin/console tenancy:install`. This generates the required configuration files and sets up the bundle. No manual DI wiring is needed—just configure your tenant resolvers (e.g., Host, Origin header) in `config/packages/tenancy.yaml`.
- Does this bundle support both database-per-tenant and shared-database models?
- Yes. The bundle supports both modes out of the box. For database-per-tenant, it switches DBAL connections dynamically. For shared-database, it uses Doctrine SQL filters (via the `#[TenantAware]` attribute) to scope queries automatically. You can toggle between modes via configuration without rewriting application logic.
- How does tenant resolution work in practice? Can I use custom resolvers?
- Tenant resolution happens once per request via kernel listeners. The bundle includes 5 built-in resolvers (Host, Origin header, CLI flag, etc.), but you can create custom resolvers by implementing the `TenantResolverInterface`. Resolvers are chainable, so you can prioritize them (e.g., check Origin header first, fall back to Host).
- Will this bundle work with Symfony Messenger for async jobs (e.g., queues)?
- Yes. The bundle automatically stamps Messenger envelopes with the active tenant and restores it when the message is consumed. This ensures async jobs (e.g., delayed commands) operate within the correct tenant context. No manual tenant propagation is required in your job classes.
- What’s the performance impact of using SQL filters for shared-database tenancy?
- The `#[TenantAware]` filter adds minimal overhead for simple queries, but complex joins or nested transactions may introduce latency. The bundle includes optimizations like query caching, and you can disable strict mode for read-heavy workloads. For high-scale shared-DB apps, consider indexing tenant columns or using read replicas.
- How does the bundle handle tenant creation/deletion at scale (e.g., 10,000+ tenants)?
- The bundle supports bulk operations for database-per-tenant setups, but large-scale deployments may require custom scripts for parallel migrations or batch processing. For shared-DB, tenant creation/deletion is lightweight, but ensure your database schema and indexes are optimized. The `tenancy:migrate` command runs migrations per tenant by default.
- Can I extend the bundle to support custom services (e.g., Redis, Elasticsearch) without modifying the core?
- Absolutely. The bundle uses a tag-based bootstrapper system (`tenancy.bootstrapper`), allowing you to add custom bootstrappers for services like Redis or Elasticsearch. Just create a service tagged with `tenancy.bootstrapper` and implement the `BootstrapperInterface`. No core changes are needed.
- Does the bundle work with Symfony’s Profiler or provide observability tools?
- Yes. The bundle includes a Profiler tab that displays the active tenant, resolution latency, and bootstrapper execution times. For production, you can integrate with Symfony’s Monolog or third-party APM tools to track tenant-related metrics like resolution failures or slow queries.
- What are the alternatives to this bundle, and why should I choose this one?
- Alternatives include custom tenancy layers or Symfony’s `DoctrineConnection` for basic DB switching, but neither provides the full-stack integration (Messenger, Cache, Mailer) or zero-boilerplate design of this bundle. Unlike Laravel’s stancl/tenancy, this is Symfony-native, with deep integration into Doctrine and Messenger. It also enforces strict tenant isolation by default, reducing data leak risks.