hakam/multi-tenancy-bundle

Flexible and production-ready multi-tenancy bundle for Symfony.

Installs: 37 209

Dependents: 0

Suggesters: 0

Security: 0

Stars: 117

Watchers: 7

Forks: 34

Open Issues: 2

Type:symfony-bundle

pkg:composer/hakam/multi-tenancy-bundle

v3.0.0 2026-02-21 15:15 UTC

This package is auto-updated.

Last update: 2026-02-23 10:52:06 UTC


README

Multi-Tenancy Bundle (Desktop Wallpaper)

Action Status Total Downloads Symfony Flex codecov

📚 Full Documentation: Documentation

🧩 Overview

The Symfony Multi-Tenancy Bundle enables scalable, production-ready multi-tenancy for Symfony applications.

Ideal for SaaS platforms, region-based services, and multi-vendor e-commerce systems, this bundle is built around a database-per-tenant architecture, giving each tenant:

  • A fully isolated database
  • Independent schema and migrations
  • Configurable connection parameters (host, driver, credentials)

It integrates seamlessly with Doctrine and Symfony's service container, offering:

  • Automatic tenant database switching at runtime via SwitchDbEvent
  • Automatic tenant resolution from HTTP requests (subdomain, path, header, or custom)
  • Separate migration and fixture paths for main vs. tenant databases
  • Dedicated TenantEntityManager service for runtime isolation

For full usage examples and advanced configuration, see the documentation.

🔄 Automatic Tenant Resolution (v3.0.0+)

Automatically resolve the current tenant from incoming HTTP requests — no manual event dispatching required.

Supported Strategies

Strategy Example Description
subdomain tenant1.example.com Extracts tenant from subdomain
path /tenant1/dashboard Extracts tenant from URL path segment
header X-Tenant-ID: tenant1 Extracts tenant from HTTP header
host client.com → tenant1 Maps full hostname to tenant
chain Multiple strategies Tries resolvers in order with fallback

Quick Configuration

# config/packages/hakam_multi_tenancy.yaml
hakam_multi_tenancy:
    resolver:
        enabled: true
        strategy: subdomain  # subdomain | path | header | host | chain
        options:
            base_domain: 'example.com'  # for subdomain strategy

Strategy Examples

Subdomain-based (e.g., acme.myapp.com):

resolver:
    enabled: true
    strategy: subdomain
    options:
        base_domain: 'myapp.com'

Header-based (for APIs):

resolver:
    enabled: true
    strategy: header
    options:
        header_name: 'X-Tenant-ID'

Path-based (e.g., /acme/dashboard):

resolver:
    enabled: true
    strategy: path
    excluded_paths: ['/api/public', '/health']

Chain strategy (fallback support):

resolver:
    enabled: true
    strategy: chain
    options:
        chain_order: [header, subdomain, path]

Accessing Resolved Tenant

The resolved tenant ID is available in request attributes:

// In a controller
$tenantId = $request->attributes->get('_tenant');

Custom Resolver

Implement TenantResolverInterface for custom logic:

use Hakam\MultiTenancyBundle\Port\TenantResolverInterface;

class CustomResolver implements TenantResolverInterface
{
    public function resolve(Request $request): ?string
    {
        // Your custom logic
        return $request->cookies->get('tenant_id');
    }

    public function supports(Request $request): bool
    {
        return $request->cookies->has('tenant_id');
    }
}

Note: Automatic resolution is disabled by default for backward compatibility. Manual SwitchDbEvent dispatching continues to work.

🚀 Quick Installation

1. Via Symfony Flex (Recommended)

composer require hakam/multi-tenancy-bundle

Symfony Flex will automatically scaffold config, register the bundle, and create:

src/Entity/Main/
src/Entity/Tenant/
migrations/Main/
migrations/Tenant/

2. Manual Installation

composer require hakam/multi-tenancy-bundle

Then register in config/bundles.php, copy the example hakam_multi_tenancy.yaml from docs, and create the required directories.

📖 Examples

The examples/ directory contains 15 ready-to-use code examples covering every feature of the bundle:

# Example Feature
01 Entity Setup TenantDbConfig entity with TenantDbConfigTrait
02 Bundle Configuration Full YAML config reference
03 Tenant Entities Tenant-scoped entities (Product, Order)
04 Database Lifecycle Create DB, switch, CRUD, CLI commands
05 Tenant Migrations Platform-agnostic migrations with Schema API
06 Resolvers All 5 resolution strategies + controller usage
07 Lifecycle Events All 6 events with subscriber pattern
08 Custom Config Provider Redis, static, and in-memory providers
09 Tenant Fixtures #[TenantFixture] attribute + CLI
10 Cache Isolation TenantAwareCacheDecorator usage
11 Tenant Context TenantContextInterface in services, Twig, listeners
12 Testing TenantTestTrait with runInTenant()
13 Shared Entities #[TenantShared] with exclusions
14 Custom Resolver JWT, query param, API key resolvers
15 Full Onboarding Flow Complete end-to-end tenant onboarding

See also the Examples documentation page for detailed explanations.

🔗 Useful Links

📄 License

MIT © Ramy Hakam