Tenant Isolation Strategy: Global Rates in a Multi-Tenant Laravel Application

Introduction

In multi-tenant applications, data isolation is key. One common challenge is determining which data should be tenant-specific and which should be global. In our Laravel platform project, we faced this question with application rates. Initially, we considered rates to be tenant-scoped, but we discovered that, due to regulatory requirements, these rates are actually global and apply across all tenants.

This post details how we refactored our application to reflect this understanding, ensuring data integrity and simplifying our database schema.

The Problem: Tenant-Scoped Rates

Our initial design included a company_id column in the rates table. This implied that each tenant (company) could have its own set of rates. This design decision led to a few problems:

  1. Migration Failures: The company_id column was defined as NOT NULL. During the seeding process, this caused errors because the seeder couldn't determine the appropriate company_id for the initial rates.
  2. Data Redundancy: Storing the same rate information for multiple tenants introduced unnecessary data duplication.
  3. Maintenance Overhead: Any changes to rate configurations would need to be applied across all tenants, increasing maintenance complexity.

The Solution: Global Rates

To address these issues, we decided to make rates global. This involved the following steps:

  1. Database Migration: We created a new migration to remove the company_id column from the rates table. This ensured that rates are no longer associated with a specific tenant.

    Schema::table('rates', function (Blueprint $table) {
        $table->dropForeign(['company_id']);
        $table->dropColumn('company_id');
    });
    
  2. Seeder Update: We modified the seed migration to no longer reference the company_id. This simplified the seeding process and removed the dependency on tenant context.

  3. Resource Adjustment: We updated the RateResource (likely a Filament resource) to remove any tenant-specific filtering. This ensured that rates are accessible globally, regardless of the current tenant.

  4. Code Cleanup: We cleaned up the Rate model, factory, import job, and any related resources to remove any references to company_id. This ensured consistency and removed potential sources of bugs.

Benefits of a Global Approach

  • Simplified Data Model: Removing the company_id column simplified the database schema and reduced data redundancy.
  • Improved Data Integrity: By having a single source of truth for rates, we eliminated the risk of inconsistencies across tenants.
  • Easier Maintenance: Updates to rates only need to be applied once, reducing the maintenance burden.

Conclusion

When designing multi-tenant applications, carefully consider the scope of your data. While tenant-specific data is often necessary, some data, like our application rates, might be better suited as global. By refactoring our application to use global rates, we simplified our data model, improved data integrity, and reduced maintenance overhead.

Actionable Takeaway: Review your multi-tenant data model and identify any tenant-scoped data that could be refactored as global to simplify your application and improve data consistency.

Tenant Isolation Strategy: Global Rates in a Multi-Tenant Laravel Application
GERARDO RUIZ

GERARDO RUIZ

Author

Share: