Implementing Multi-Tenant Data Isolation in MODX via Contexts
Learn how to use MODX Contexts to implement multi-tenant data isolation, ensuring resources, settings, and cache are logically segregated between different sites.
03 Nov 2025, 12:24 UTC

The problem
Running multiple websites from a single MODX installation risks data bleed where resources, settings or cached fragments from one site appear on another. The goal is strict logical isolation per tenant without maintaining separate CMS installs.
The MODX Context provides a logical partition that segregates resources and system settings. Assigning a request to a specific context ensures the CMS only queries data belonging to that tenant.
Architectural requirements
- Resource segregation: Resources in Context A must be unreachable via the URI structure of Context B.
- Configuration independence: Each tenant needs unique system settings such as site name and API keys without affecting the global installation.
- Cache partitioning: MODX cache must separate fragments to prevent a tenant from serving another's cached HTML.
- Administrative boundary: Managers should only edit resources within their assigned context.
Smallest suitable design
The smallest viable design uses native Contexts and hostname mapping.
Context configuration
Create a new Context in the MODX Manager. The context key, for example tenant_alpha, acts as a partition identifier for resources and settings.
Hostname mapping
Route traffic to a context via a custom plugin or snippet that maps the incoming hostname or URI to a context key. Context-specific settings define the base URL for each context.
Resource assignment
Create resources with the target context_key instead of the default web context. This scopes queries to the tenant.
Trust and data boundaries
The boundary is enforced at query time when the context is set for a request. Context-specific settings enable unique configuration per tenant.
Critical boundary risks:
- Global snippets: Snippets are shared. A snippet that queries without scoping to the current context can leak data. Use $modx->getContextKey() to scope fetches.
- Shared media: The File Manager is shared by default. Isolate assets with context-specific base paths for uploads.
- Context switching: Incorrect context switching in custom plugins can lead to data leakage if not strictly validated.
Operational checks
Resource isolation
Create two contexts and verify resources created in one are invisible in the other. Create a resource in tenant_alpha and tenant_beta with the same alias and confirm distinct content is served per hostname.
Cache inspection
Inspect core/cache to confirm cached files are organized by context. The MODX cache mechanism respects context boundaries.
Setting override test
Set site_name globally then override it for tenant_alpha. Load both tenants and verify the override applies only to tenant_alpha.
Failure modes
| Failure mode | Cause | Result |
|---|---|---|
| Context leakage | Hardcoded web context in custom plugins | Tenant B sees Tenant A's content |
| Performance degradation | Excessive context-specific settings | Slower system settings lookups |
| Routing loop | Incorrect site_start or base URL configuration | HTTP 500 or redirect loop |
Conditions that change the design
- Database scale: Large numbers of contexts increase size of system settings table and can impact query performance.
- Strict compliance: Regulatory requirements demanding physical database separation require separate DB users or schemas.
- Customization divergence: Tenants requiring different MODX versions or incompatible extras need multi-instance.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.