Building a Multi-Tenant Application with Symfony: A Guide

Building a Multi-Tenant Application with Symfony: A Guide

When building SaaS (Software as a Service) platforms, it’s essential to manage multiple tenants effectively. This means supporting multiple stores or clients using the same application while ensuring that each tenant has a distinct environment for their data, configurations, and, in some cases, custom features.

In this blog, we’ll explore how to build a multi-tenant application using Symfony, focusing on a shared database approach that’s simple, flexible, and scalable.


What is Multi-Tenancy?

In multi-tenancy:

  • A tenant is a distinct user or client of your SaaS app.
  • Each tenant has access to their own data, settings, and sometimes their own customizations.
  • Shared Database: Multiple tenants share the same database, but data is logically separated using a tenant_id to identify records that belong to each tenant.

Why Symfony for Multi-Tenancy?

Symfony is one of the most flexible and robust PHP frameworks. It allows for customizations at the routing, database, and service layers — making it an excellent choice for building multi-tenant SaaS applications.

Approaches to Multi-Tenancy in Symfony

There are two common approaches:

  1. Separate Database per Tenant — Each tenant has its own database.
  2. Shared Database with Tenant Isolation — All tenants share the same database, but their data is isolated via a tenant_id.

In this guide, we will use the Shared Database with Tenant Isolation approach, which is more efficient and scalable when you have a large number of tenants.


Step-by-Step Guide to Building a Multi-Tenant SaaS with Symfony

1. Define Your Tenant Model

First, we need to define a Tenant entity that stores the essential information for each tenant.

This model represents a tenant in your application, where the customDomain can be used to map the tenant’s domain to their specific store.

2. Detect the Tenant from the Domain

You’ll need to detect the tenant based on the domain or subdomain of the incoming request. This is typically done using Symfony’s request listener.

Here’s an example of how to extract the domain and match it to a tenant:

  • Here, we’re using the Host header from the HTTP request to get the domain (store1.yoursaas.com, for example).
  • We then look up the tenant by matching the customDomain field in the Tenant entity.
  • If no tenant is found for the domain, an exception is thrown.

3. Use a Doctrine Filter to Isolate Tenant Data

Once you’ve detected the tenant, you need to ensure that all database queries are filtered by the tenant’s tenant_id. The easiest way to do this is to use a Doctrine filter.

This filter automatically adds the tenant_id to every query, ensuring that tenants can only access their own data.

In your services configuration, you would register the filter like this:

4. Update the Routing Based on Tenant Domain

In a multi-tenant setup, you can use subdomains to route requests to different tenants. You’ll need to configure your NGINX or web server to route the requests based on subdomains (e.g., store1.yoursaas.com).

Example NGINX configuration:

This configuration accepts all domains and forwards them to your Symfony app. Symfony will then resolve which tenant to serve based on the host.


5. Handling Custom Domains

If your tenants want to use their own custom domains (e.g., mystore.com instead of store1.yoursaas.com), you can:

  1. Allow users to add their custom domain via the admin interface.
  2. Store the custom domain in the Tenant entity.
  3. Add DNS and SSL configurations for custom domains (via Let’s Encrypt or another service).
  4. Map the custom domain to the correct tenant using the previously discussed domain detection logic.

Conclusion

Building a multi-tenant SaaS app with Symfony allows for great flexibility in scaling, isolating tenant data, and customizing tenants’ experiences. By using a shared database with logical isolation (via tenant_id), you can manage multiple clients while keeping things efficient and scalable.

With the steps above, you can:

  • Detect tenants by domain
  • Automatically filter tenant data in your database queries
  • Handle custom domains for clients

This architecture is ready to scale as your platform grows, allowing you to add features like:

  • Custom themes
  • Tenant-specific configurations
  • Dedicated services or databases per tenant (if needed later)

By starting with a strong foundation like Symfony and keeping things flexible from the start, you’ll be in a great position to grow your SaaS app.

Crazy about CRO?

15+ ideas for growing your eCommerce store

Join & get tip & tricks for eCommerce Growth

We don’t spam! Read more in our privacy policy

Tags:

Leave a Reply

Your email address will not be published. Required fields are marked *