Multi-tenant Platforms

You serve multiple customers from shared infrastructure. Isolation must be enforced. Entitlements differ per tenant.

What decisions matter here?

Multi-tenancy turns every request into a boundary decision:

These decisions happen at the edge, before requests reach your services.

What goes wrong today?

Tenant checks in application code Every service checks if (tenant.tier === 'enterprise'). The logic is scattered, inconsistent, and hard to audit.

Feature flag sprawl You use LaunchDarkly for features, a homegrown system for entitlements, and application code for tenant isolation. Three systems, three sources of truth.

Noisy neighbor problems One tenant’s traffic spike affects others. Rate limiting is per-service, not per-tenant. You can’t enforce fair usage at the gateway.

Entitlement disputes Customer claims they should have access to a feature. You check the feature flag system, the billing system, and the entitlement database. They all say different things.

What Hexarch changes structurally

Application Identity Hub

From the Application interface and IdentityManager.tsx:

interface Application {
  id: string;
  name: string;
  owner: string;
  subscriptions: Subscription[];
  credentials: Credential[];
}

Each tenant is a formal application identity. Their subscriptions, credentials, and entitlements are managed in one place. The gateway knows this identity and enforces accordingly.

Before: Tenant context scattered across services After: Centralized tenant identity with gateway-enforced entitlements

Granular Policy Scoping

From the PolicyScope enum:

enum PolicyScope {
  GLOBAL,   // All tenants
  API,      // Specific API
  VERSION,  // Specific version
  PLAN,     // Specific access plan (tenant tier)
  ROUTE     // Specific endpoint
}

Policies apply at different granularities. A global security policy for all tenants. A rate limit policy per plan tier. A route-level policy for sensitive endpoints.

Before: One-size-fits-all or per-service configuration After: Hierarchical scoping from global to route-level

Tier-Based Entitlements

From the AccessPlan interface:

interface AccessPlan {
  name: string;  // 'Free', 'Business', 'Enterprise'
  quota: { value: number; unit: 'Requests'; period: string };
  rateLimit: { requestsPerSecond: number; burst: number };
  policies: Policy[];  // Tier-specific policies
}

Each tier has its own quotas, rate limits, and policies. Free tenants get 100 requests/day. Enterprise gets unlimited. The gateway enforces—your services receive only authorized, within-quota requests.

Before: Tier checks in application code After: Tier enforcement at gateway, services receive clean traffic

Feature Entitlements via Policy

From the AdminDecisionDashboard.tsx decision feed:

interface DecisionRecord {
  feature: string;  // 'policy_generation', 'analytics', 'custom_policies'
  tier: string;     // 'free', 'pro', 'enterprise'
  decision: 'ALLOW' | 'DENY';
  reason: string;   // 'tier=pro, feature not in plan'
}

Features are policy decisions. Tenant on Free tier tries to access Analytics → DENY, reason: “feature not in tier.” The decision is recorded, auditable, consistent.

Before: Feature flags + entitlement database + billing check After: One policy decision with full audit trail

Per-Tenant Rate Limiting

From the Policy interface with targetRef:

interface Policy {
  scope: 'PLAN';
  targetRef: { planId: string };
  config: {
    ratePerMinute: number;
    burstBuffer: number;
  };
}

Rate limits are per-plan, not global. Free tier gets 1 req/s. Enterprise gets 100 req/s. No noisy neighbors—each tenant’s traffic is shaped independently.

Before: Global rate limit, hope for fairness After: Per-tenant limits enforced at gateway

Tenant Isolation Model

LayerTraditionalHexarch
IdentityJWT claims + application parsingFormal Application entity
EntitlementsFeature flags + billing lookupSubscription with version-locked plans
Rate limitingPer-service, inconsistentPer-plan at gateway
Feature accessif (tier === 'enterprise')Policy decision with audit
Audit trailScattered logsPer-tenant decision stream

The Developer Portal for Tenants

From DeveloperPortal.tsx:

Tenants can self-serve through the portal:

  1. Register Application: Create their tenant identity
  2. Browse API Catalog: See available APIs and versions
  3. Subscribe to Plans: Select their tier
  4. Track Entitlements: View active subscriptions and quotas

Governance happens in the background. The gateway propagates entitlements. Traffic is shaped before it reaches your services.

Try It