Skip to content

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:

  1. Extracts tenant_id from the request's JWT claim (injected at token-issuance time by a pre-token hook).
  2. Looks up the tenant_id → policy-store-id mapping from a tenant configuration store (DynamoDB).
  3. 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-id mapping in DynamoDB becomes a hot-path dependency. Cache it.

Implementation checklist

  1. Per-tenant Cognito pool (or shared pool with tenant_id custom attribute). Pre-token hook injects tenant_id claim.
  2. Policy store creation flow on tenant signup; delete flow on churn.
  3. tenant_id → policy-store-id mapping in a fast-lookup store (DynamoDB); cache aggressively.
  4. Lambda authorizer reads tenant_id from the JWT, resolves policy-store-id, calls AVP against that store.
  5. Zero-trust re-verification at the backend: backend propagates tenant_id to downstream services, re-calls AVP against the tenant's store before data access.
  6. Data-layer tenant-context enforcement. RDS / database configured to reject requests without tenant context.

Seen in

Last updated · 200 distilled / 1,178 read