How to Separate Laravel Configuration from Tenant Settings

keep deployment-level configuration in Laravel’s config files, and store changeable tenant-specific values in a database-backed settings layer.

Moving every environment value into a settings table creates new security and startup problems. The safer design is to give each kind of value one clear home.

Use two configuration layers

  1. Bootstrap configuration: Keep database hosts, cache drivers, queue drivers, encryption keys, and other values required to start the application in environment variables and config/*.php.

  2. Runtime settings: Store values that administrators may change without a deployment in the database. Examples include feature switches, display preferences, and tenant-specific integration options.

Application code should read environment variables through Laravel config files. After configuration is cached, calling env() directly in application code can produce surprising results. Use config() for bootstrap values.

Decide where each database setting belongs

In a separate-database tenancy model, settings usually have two scopes:

  • Central settings apply to the whole platform or help identify and connect a tenant.
  • Tenant settings belong only to one tenant and live in that tenant’s database.

The application must identify the tenant and initialize its database connection before loading tenant settings. This is why tenancy should be established before building the tenant settings interface.

Use a clear fallback order

A settings service can resolve values in a predictable order:

  1. Use the tenant-specific value when one exists.
  2. Otherwise use an approved central default.

  3. Otherwise fall back to the Laravel config value.

This keeps defaults deployable while still allowing controlled overrides. Cache resolved settings with a tenant-specific cache key, and invalidate that cache immediately after an administrator saves a change.

Protect sensitive settings

Some credentials may need to vary by tenant. If authorized administrators must manage them at runtime, encrypt them at rest, restrict the settings page by role, mask stored values in the interface, and never write plaintext secrets to logs.

Do not move the application encryption key or the credentials needed to reach the settings database into that same database. The application must already possess those values before it can read anything from storage.

Common mistakes and fixes

  • Cause: One untyped key-value table accepts anything. Fix: define allowed keys, types, validation rules, and scope.
  • Cause: Tenant settings load before tenancy is initialized. Fix: identify the tenant and switch the database connection first.

  • Cause: Cached values leak between tenants. Fix: include the tenant identifier in every settings cache key.

  • Cause: Secrets appear in forms or logs. Fix: encrypt, mask, authorize, and redact them.

Reset tenant context in long-lived workers

Requests are not the only place tenant state can leak. Queue workers and other long-lived processes must establish the intended tenant before loading settings and clear that context after the job. Include a regression check that alternates two tenants in the same process, including a job that throws an exception.

Keep Laravel config as the stable bootstrap layer, then add a tenant-aware settings service for values that genuinely need runtime control. The next action is to classify every current setting as bootstrap, central, or tenant-specific before creating the settings table.

Reference: Laravel configuration caching.

Leave a Reply