Skip to main content
A well-designed authorization model is easier to understand, debug, and maintain. It also performs better and scales more gracefully as your application grows. This guide covers key principles for modeling authorization in OpenFGA.

Core Principle: Model Your Domain, Not a Meta-Model

The most common mistake when starting with OpenFGA is creating an overly generic model that can represent “anything.” While this seems flexible, it trades clarity for abstraction and often hurts performance.
Rule of ThumbIf end-users can define it, store it in tuples. If it’s built into your application, define it in the model.For example: built-in roles like “admin” or “billing_manager” should be relations in your model. User-defined custom roles should be stored as tuples with a role type.
Define types and relations that mirror your application’s domain. If your app has organizations, projects, and documents, model exactly that with explicit relationships: Notice how this model has a clear hierarchy (organization → project → document) where each type and relationship directly reflects the application’s domain. Permission inheritance follows a well-defined path that’s easy to understand and audit. This approach has several advantages:
  • Enhanced clarity and maintainability: Authorization logic is easier to understand, debug, and maintain. Developers and security auditors can readily grasp the meaning of each type and relationship just by reading the model.
  • Better performance: Models with specific types and flatter hierarchies perform better. OpenFGA processes queries more efficiently with well-defined types compared to navigating complex recursive relationships within generic types.
  • Easier evolution: OpenFGA’s modeling language is designed to be adaptable. You can define numerous distinct types and relationships without significant overhead. Model changes rarely require data migrations, allowing you to evolve your model as your application grows.
  • Team autonomy with modules: Resource types owned by each application team can be maintained in independent modules. You can control which application can write to specific resource types through API credentials, providing better security boundaries.
The model below can technically represent any organization hierarchy, any resource hierarchy, and any role hierarchy:While flexible, this approach creates problems:
  • The model doesn’t communicate what your application actually does
  • To understand the actual relationships you need to rely on tuples, e.g., the fact that a project can have documents.
  • Generic recursive relations are slower to evaluate
  • You can’t use modules to isolate different resource types
  • ListObjects returns mixed results (all “resources” instead of just “documents”)

Modeling Roles

Most applications have roles. The key question is: are they built-in or user-defined?

Built-in Roles

For roles that come with your application (admin, member, viewer, etc.), define them directly as relations: Adding new built-in roles is straightforward: add a relation to the model. This happens infrequently and doesn’t require data migration.

Custom Roles (User-Defined)

Some applications let end-users create their own roles. In this case, combine static roles with a dynamic role type: This hybrid approach gives you the clarity of static roles for common cases while supporting custom roles when needed. For more details, see Modeling Roles and Custom Roles.

Modeling Organizational Structures

B2B SaaS applications often have two distinct organizational requirements:
  1. Super-admin access: Your company’s employees need to access customer data for support or disaster recovery
  2. Customer hierarchies: Your customers have their own organizational structures

Super-Admin Access

For internal support and admin access, use a dedicated system type rather than making organizations recursive: This approach:
  • Clearly separates your internal access from customer access
  • Avoids recursive relations (faster to evaluate)
  • Makes audit and compliance reviews easier
See a complete super-admin example for more details.

Customer Organization Hierarchies

If customers need hierarchical organizations, prefer explicit types for each level when the structure is well-defined: This makes the hierarchy explicit: organizations contain departments, and department members inherit from the organization. If the hierarchy depth is truly dynamic (customers can nest arbitrarily), then add recursion only where needed: Now you have two distinct hierarchies:
  • System hierarchy: Non-recursive, for your internal super-admin access
  • Organization hierarchy: Recursive only if customers truly need arbitrary nesting
Prefer explicit types when possible; use recursion only when the depth is genuinely unbounded.

Modeling Resource Types

Applications have different kinds of resources: documents, folders, projects, tickets, accounts, etc. Some have parent-child relationships (folders contain documents, projects contain tickets).

Use Specific Types, Not a Generic “Resource”

Define a type for each kind of resource in your application: Benefits of specific types:
  • Accurate ListObjects results: Querying for documents returns only documents, not all resources
  • Type-specific permissions: can_print makes sense for documents but not folders
  • Clearer model: Each type shows exactly what permissions apply to it
  • Module support: Different teams can own different resource types
Problems with this approach:
  • ListObjects returns mixed results (folders, documents, and everything else)
  • You end up with a superset of all permissions, making it unclear which apply to what
  • No way to use modules for team ownership
  • Harder to understand and audit

Quick Reference

Check out these related resources for more information about modeling in OpenFGA

Custom Roles

Learn how to implement user-defined custom roles.

Modular Authorization Models

Learn how to break down your authorization model into modules.

Modeling Roles

Detailed guidance on role-based access control patterns.

Building Blocks

Understand the fundamental concepts for building authorization models.
Last modified on September 28, 2026