Skip to main content
Microservices repeat the same pattern: each service ends up with its own roles table, its own permission checks, and its own subtle drift. OpenFGA centralizes that into a single authorization service that every microservice consults.

The pattern

  • One OpenFGA store holds the model and tuples for the whole system.
  • Each microservice calls check, list-objects, or list-users over the OpenFGA API rather than implementing its own permission logic.
  • Writes go through the service that owns the relationship (e.g. the membership service writes member tuples; the document service writes can_share tuples).

Why this beats per-service authorization

  • One model to reason about. Cross-service questions (“can this user read this document via their team’s project access?”) become a single graph traversal instead of a coordination dance.
  • No more drifted roles tables. A relation defined once in the OpenFGA model is the same relation in every service.
  • Reverse queries work across services. list-objects returns every resource the user can access, regardless of which service owns it.

Simplified model

The membership service writes team#member tuples; the project service writes project#team; the document service writes document#project. Any service — including ones that only read documents — answers permission questions with a single check against the same OpenFGA store, instead of reimplementing team/project/document role logic locally.

Operational shape

  • Latency. Run OpenFGA close to the calling services. Sizing depends on workload, but production deployments routinely hit thousands of RPS at single-digit-to-low-double-digit ms p99 on PostgreSQL.
  • Caching. OpenFGA supports check caching; pair with short cache TTLs in clients for hot paths.
  • Observability. Treat authorization decisions as a first-class metric. Track check rate, latency, and authorization failures per service.
Last modified on September 28, 2026