Skip to main content
Version: 2026.04.0

Enterprise Developer Gap Analysis

This page is a candid assessment of what the Multi-Tenancy module provides today versus what a developer building an enterprise-grade, multi-tenant application with existing authentication infrastructure would typically expect. Use it to make informed architecture decisions before committing to this module in production.

Maturity: Stable, With Explicit Boundaries

The validated core and shipped integration packages are stable for the documented pooled shared-table model. The items below are still real adoption boundaries, but they are platform and rollout concerns, not evidence that the documented core is still in preview.


What the module does well

CapabilityStatus
Resolving tenant identity from JWT claims, headers, route values, subdomain, or membershipFully implemented
Membership-validated tenant selection (MembershipValidatedTenantResolutionStrategy)Fully implemented
Enforcing tenant isolation on authenticated requests (403)Fully implemented
Per-tenant rate limiting (in-process)Fully implemented
Pluggable tenant rate limiter abstraction (ITenantRateLimiter)Fully implemented
EF Core write enforcement — sets TenantId on new entities, blocks cross-tenant mutationsFully implemented
EF Core read-isolation guard (throws when tenant-owned entities have no filter provider)Fully implemented
Super-admin bypass policy hook (ITenantBypassPolicy)Fully implemented
Membership-store caching decorator (AddPrimusMultiTenancyMembershipCaching)Fully implemented
Distributed membership caching (AddPrimusMultiTenancyDistributedMembershipCaching)Fully implemented
Distributed rate limiting (AddPrimusMultiTenancyDistributedRateLimiting)Fully implemented
Tenant lifecycle helpers (Suspend, Activate, SoftDelete)Fully implemented
Tenant hard-delete endpoint + store operation (DeleteTenantAsync)Fully implemented
Tenant offboarding data-retention contract (ITenantDataRetentionService)Fully implemented
Tenant list/search/summary management endpointsFully implemented
Structured audit sink (ITenantAuditSink) with 18 event typesFully implemented
Tenant provisioning hook (ITenantProvisioningHandler)Fully implemented
Background context propagation (TenantExecutionContext + AmbientTenantContextAccessor)Fully implemented
Tier-based rate-limiting (PerTierRateLimits)Fully implemented
Non-relational resource isolation policy contract (ITenantResourceIsolationPolicy)Fully implemented
In-Memory store for local development and unit testsFully implemented
RBAC scope composition helper (ResolveTenantIdForRbac())Fully implemented

Known gaps

1. Distributed rate limiting still depends on distributed cache registration

Impact: High for multi-instance deployments.

AddPrimusMultiTenancyAspNetCore() auto-selects DistributedTenantRateLimiter only when IDistributedCache is registered. Without distributed cache registration, the fallback is still in-memory and process-local.

Resolution: Register IDistributedCache (Redis, SQL Server cache, etc.), and optionally call AddPrimusMultiTenancyDistributedRateLimiting(...) to enforce explicit distributed behavior.

builder.Services.AddPrimusMultiTenancyAspNetCore();
builder.Services.AddStackExchangeRedisCache(o => o.Configuration = "localhost:6379");
builder.Services.AddPrimusMultiTenancyDistributedRateLimiting();

For fully custom quota logic, implement ITenantRateLimiter and register it with AddSingleton<ITenantRateLimiter, YourLimiter>().


2. No admin UI or management dashboard

Impact: Low to medium, depending on team.

The module includes endpoints for list/search/summary/get/upsert/activate/suspend/soft-delete/hard-delete operations backed by ITenantStore. It still does not ship a first-party admin UI.

Workaround: Use built-in endpoints for baseline workflows, or build application-level endpoints for custom validation, workflows, and governance.


3. Membership caching is still in-process unless distributed cache is enabled

Impact: Medium for high-traffic APIs.

AddPrimusMultiTenancyMembershipCaching(...) provides an in-process cache wrapper. For multi-instance deployments, use AddPrimusMultiTenancyDistributedMembershipCaching(...) to back membership caching with IDistributedCache so cache entries can be shared across replicas.

Workaround: If you need custom serialization/eviction behavior, replace the decorator with your own ITenantMembershipStore implementation.


4. Subdomain resolution still requires consistent host configuration

Impact: Low, but easy to misconfigure.

SubdomainTenantResolutionStrategy reads the first segment of the Host header (e.g., acme from acme.example.com). It now supports development hosts like acme.localhost through SubdomainDevelopmentHosts, but production still requires consistent DNS.

Workaround: Leave EnableSubdomainResolution: false locally and use header- or claim-based resolution during development. Enable subdomain resolution only in environments with proper DNS wildcard records.


5. Isolation scope: pooled shared-table only

Impact: Architectural — depends on compliance and data-residency requirements.

All tenants share the same schema. The TenantId column is the only isolation boundary. This is appropriate for most SaaS workloads but does not satisfy regulations or contractual obligations that require physical data separation (e.g., separate database or schema per customer).

Resolution: This is by design and will not change within this package. For dedicated-DB or schema-per-tenant isolation, integrate an orchestration layer (e.g., Azure Elastic Pools + a custom ITenantStore that provisions per-tenant databases) alongside or instead of this package.


6. No built-in enforcement for file, blob, or search systems

Impact: Medium for applications with unstructured storage.

The module enforces isolation only on EF Core-tracked entities. It now provides ITenantResourceIsolationPolicy to centralize naming/prefix rules for non-relational resources, but platform-specific enforcement remains application-owned.

Workaround: Prefix storage container or index names with {tenantId}- at the application layer, and validate tenantId against the resolved TenantContext before all non-relational operations.


7. Hard-delete data purge orchestration remains application-owned

Impact: Low to medium, depending on data-residency requirements.

The module now supports hard-delete at tenant-record level (DELETE /primus/tenants/{tenantId} and DeleteTenantAsync). Full offboarding purge across related module data and external systems is still not automatic.

Workaround: Implement ITenantDataRetentionService and orchestrate cross-system purge jobs after retention windows.


8. Billing-plan enforcement remains application-owned

Impact: Medium for SaaS monetization.

The package now supports tier-aware rate limits (PerTierRateLimits, TenantTierMetadataKey, DefaultTenantTier) and endpoint feature gating (UsePrimusTenantEntitlements(), RequirePrimusFeature(...), PerTierEntitlements). Billing integration (invoice state, grace windows, payment retries, and downgrade timing) is still application-owned.

Workaround: Use built-in entitlements for request-time access control, and integrate billing providers to update tier metadata and entitlement sets.


GapRiskStatus
Distributed rate limiting depends on IDistributedCache registrationHigh (multi-instance)Register distributed cache, optionally call AddPrimusMultiTenancyDistributedRateLimiting(...)
Membership cache is in-process by defaultMedium (multi-instance perf)Use AddPrimusMultiTenancyDistributedMembershipCaching(...)
No admin UILow–MediumWorkaround: custom Portal integration
Subdomain resolution requires DNS disciplineLowSubdomainDevelopmentHosts improves local workflows; production still needs DNS
Pooled shared-table isolation onlyArchitecturalBy design — dedicated-DB and schema-per-tenant are out of scope
No built-in blob/search enforcementMediumUse ITenantResourceIsolationPolicy + storage-layer enforcement
Cross-system hard-delete orchestrationLow–MediumImplement via ITenantDataRetentionService + purge job
Tiered feature entitlementsLowBuilt-in via UsePrimusTenantEntitlements() + RequirePrimusFeature(...) + PerTierEntitlements