PATTERN Cited by 1 source
Per-tenant policy store¶
Shape¶
In a multi-tenant SaaS using
Amazon Verified Permissions,
instead of putting all tenants' policies in one shared policy store
and scoping every rule by tenant_id, create one policy store per
tenant. The runtime authorizer:
- Extracts
tenant_idfrom the request's JWT claim (injected at token-issuance time by a pre-token hook). - Looks up the
tenant_id → policy-store-idmapping from a tenant configuration store (DynamoDB). - Calls
AVP.IsAuthorized(policy_store_id=..., ...)against the tenant-specific store.
(Source: sources/2026-02-05-aws-convera-verified-permissions-fine-grained-authorization)
Why it works¶
Convera chose per-tenant policy stores for four stated reasons:
- Low-effort tenant policy isolation. Tenants' policies can't accidentally reference each other's resources — the store boundary is physical.
- Per-tenant customization of templates + schema. If tenant A needs a different Cedar schema (different entity types, different attributes) than tenant B, per-tenant stores support that directly. A shared-store approach forces a union schema.
- Low-effort tenant onboarding / offboarding. Create a new store on signup, delete it on churn. No risk of leaving orphaned policies in a shared store.
- Per-tenant policy-store resource quotas. AVP's quotas (on policies per store, requests per store, etc.) apply per store — one noisy tenant can't exhaust the platform quota; a large tenant gets its own quota budget.
When to use vs shared-store-with-tenant-scoped-policies¶
Use per-tenant when:
- Tenant isolation is a compliance / regulatory requirement.
- Tenants' policy models genuinely diverge (different schemas or templates).
- Tenant count is bounded and manageable (hundreds to low thousands).
- Per-tenant policy authorship (tenant admins manage their own policies) is in scope.
Use shared store with tenant-scoped policies when:
- All tenants share one policy model.
- Tenant count is very high (tens of thousands +) and hits AVP per-account policy-store limits.
- Central authorship model; tenants don't author policies.
- You want fewer resources to manage.
Trade-offs¶
- Store proliferation. One store per tenant means N stores to create, back up, monitor, and reason about. Platform-admin operations (e.g., "apply this patch policy to all tenants") have to fan out.
- Cross-tenant-platform policies (e.g., "platform admins can see across tenants") live in a separate store, or must be replicated to every tenant store.
- Account-level AVP limits. Check AVP's quota on number of policy stores per account — ceiling on tenant count this pattern scales to.
- Mapping store availability. The
tenant_id → policy-store-idmapping in DynamoDB becomes a hot-path dependency. Cache it.
Implementation checklist¶
- Per-tenant Cognito pool (or shared pool with tenant_id
custom attribute). Pre-token hook injects
tenant_idclaim. - Policy store creation flow on tenant signup; delete flow on churn.
tenant_id → policy-store-idmapping in a fast-lookup store (DynamoDB); cache aggressively.- Lambda authorizer reads
tenant_idfrom the JWT, resolves policy-store-id, calls AVP against that store. - Zero-trust
re-verification at the backend: backend propagates
tenant_idto downstream services, re-calls AVP against the tenant's store before data access. - Data-layer tenant-context enforcement. RDS / database configured to reject requests without tenant context.
Seen in¶
- sources/2026-02-05-aws-convera-verified-permissions-fine-grained-authorization
— Convera's multi-tenant SaaS flow: per-tenant Cognito pool +
tenant_idJWT claim + DynamoDBtenant_id → policy-store-idlookup + per-tenant AVP policy store + backend zero-trust re-verification + RDS tenant-context enforcement.
Related¶
- systems/amazon-verified-permissions — provides the policy-store-per-tenant substrate.
- concepts/tenant-isolation — the property this pattern implements for the authorization layer.
- patterns/lambda-authorizer — the hot-path compute that resolves tenant and calls AVP.
- patterns/zero-trust-re-verification — the complementary data-layer enforcement pattern.
- patterns/pre-token-generation-hook — upstream: injects
tenant_idinto the JWT.