x/tenant Primer
x/tenant Primer
Section titled “x/tenant Primer”Beta — API is stable within a minor version. Check Release Posture and Extension Maturity before adopting in production.
Open this page after x/* Family when the change is clearly inside a multi-tenant capability boundary rather than the smallest canonical service shape.
x/tenant is Plumego’s multi-tenancy extension: it owns tenant resolution, policy evaluation, quota management, rate limiting, tenant-aware store adapters, and session lifecycle backed by JWT state. Reference apps should not depend on this by default — it only enters when the service needs explicit multi-tenant isolation.
Stability and adoption
Section titled “Stability and adoption”Tenant isolation is security-sensitive, but that does not turn x/tenant into
a stable root. Check x/tenant/module.yaml, Release Posture,
and Extension Maturity before adopting it.
For production services, keep tenant policy and storage choices behind
application-local interfaces so upgrades stay contained.
Start here when
Section titled “Start here when”- you are resolving a tenant identity from a request (header, subdomain, JWT claim)
- you are evaluating a tenant policy or permission at the middleware layer
- you are enforcing per-tenant quota or rate limits with
Retry-Afterfeedback - you are building a tenant-aware store adapter that scopes queries to the current tenant
- you are managing JWT-backed tenant session state or session lifecycle
Do not start here when
Section titled “Do not start here when”- the change is about app bootstrap or generic middleware registration — that belongs in
coreandmiddleware - the change introduces business-specific tenant onboarding flows or product policy — keep that in application code
- the work is generic database abstractions without tenant scoping — start from
store - the change needs resilience wrappers shared across tenants — start from
x/resilience
First files to read in the current repository
Section titled “First files to read in the current repository”x/tenant/module.yamlx/tenant/resolve/x/tenant/policy/x/tenant/quota/x/tenant/ratelimit/x/tenant/session/x/tenant/store/
Public entrypoints
Section titled “Public entrypoints”Start with these concrete surfaces when wiring a service:
resolve.Middlewareto derive a tenant ID from authenticated request state, a custom extractor, or headerspolicy.Middlewareto reject requests that fail tenant policy before the handler runsquota.Middlewareandratelimit.Middlewarefor tenant-scoped budget and rate feedbacksession.SessionCheckandsession.NewJWTStateStorewhen tenant session state must be checked on each requeststoreadapters only after the request path already carries an explicit tenant identity
Concrete ownership examples
Section titled “Concrete ownership examples”Keep it in x/tenant when the work is about | Move out when the work becomes |
|---|---|
Resolving tenant ID from request context via resolve — header, claim, or subdomain | business onboarding flows or product-specific tenant provisioning |
policy evaluation: checking tenant permissions in middleware before route handlers | core or stable middleware learning tenant internals |
quota and ratelimit: per-tenant budget enforcement with Retry-After and remaining-budget headers | generic rate limiting not scoped to a tenant identity |
store: tenant-scoped query adapters that prefix or filter by tenant key | raw database abstractions or unscoped persistence helpers |
session: JWT-backed session state with tenant context, lifecycle, and revocation | generic auth token issuance or security primitives in security |
Why this primer exists
Section titled “Why this primer exists”Multi-tenancy is a cross-cutting concern that, if implemented poorly, becomes a source of data isolation failures. x/tenant enforces a hard constraint: stable roots must never learn tenant internals. Tenant resolution and policy flow must stay explicit and transport-layered; implicit globals or bootstrap magic that resolves the tenant context silently are a stop condition.