High-Cardinality Entities
Learn when to use FGA for authorization and when to handle access control in your application.
We recommend using FGA for lower-cardinality resources and handling high-cardinality entities in your application. This guide explains why and shows you how.
Lower-cardinality resources like workspaces, projects, and environments are natural boundaries for role assignments:
- Users need explicit roles – You assign someone as a project editor or workspace admin
- Sharing matters – You grant external collaborators access to specific resources
- Permissions vary by resource – Different teams have different access to different projects
- Long-lived and stable – These resources are created infrequently and change slowly, so keeping them in FGA is straightforward
High-cardinality entities like rows, artifacts, and messages rarely need this. You don’t typically assign someone as a “row editor” or “message viewer” – they inherit access from the container they’re in. Defining roles and permissions for millions of individual messages would be operationally complex without adding value.
Some authorization systems encourage storing entities such as individual files, messages, and rows as relationships in FGA. After working with many customers on authorization design, we’ve found this creates more problems than it solves. High-cardinality entities are created frequently, change often, and exist in volumes that make keeping two systems in sync impractical. Your database is already the source of truth for these entities, and access is almost always inherited from a parent container rather than granted individually.
Sync to FGA (lower cardinality):
- Organizations, workspaces, projects
- Environments, pipelines, apps
- Repositories, dashboards, teams
Keep in your application (high cardinality):
- Individual files, messages, comments
- Row-level data within tables
- Logs, events, audit records
- Anything with millions of instances per organization
To check access to high-cardinality entities, your application should traverse up to the nearest FGA-managed parent before making the authorization check:
For deeply nested structures, walk up the hierarchy to find the FGA-managed parent:
For organization-level permissions, you can skip the FGA API call entirely by checking JWT claims:
- No sync overhead – High-cardinality entities stay in your database, not FGA
- Single source of truth – Your database owns the entity data
- Fast path available – JWT claims can skip API calls for org-level permissions
- Flexible traversal – Your app controls how entities map to FGA resources
- Resources – Register and manage FGA resources
- Access Checks – Perform authorization checks
- AuthKit Integration – Embed permissions in access tokens