> ## Documentation Index
> Fetch the complete documentation index at: https://openfga.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Microservices Authorization

> Centralize authorization across microservices with OpenFGA. One model, one store, one set of decisions — instead of a roles table per service.

export const OpenFGACodeBlock = ({code, title}) => {
  const [ready, setReady] = useState(false);
  useEffect(() => {
    if (window.openfgaDsl) {
      setReady(true);
      return;
    }
    let script = document.querySelector('script[src="/openfga-dsl-highlight.js"]');
    const loaded = () => {
      if (window.openfgaDsl) setReady(true);
    };
    if (!script) {
      script = document.createElement('script');
      script.src = '/openfga-dsl-highlight.js';
    }
    script.addEventListener('load', loaded);
    if (!script.isConnected) document.head.appendChild(script);
    return () => script.removeEventListener('load', loaded);
  }, []);
  const trimmed = code.replace(/^\n/, '').replace(/\n$/, '');
  const tokens = ready && window.openfgaDsl ? window.openfgaDsl.tokenize(trimmed) : [{
    text: trimmed,
    type: 'default'
  }];
  const colors = ready && window.openfgaDsl ? window.openfgaDsl.colors : {};
  const themeStyle = {
    '--openfga-dark-background': colors.background,
    '--openfga-dark-default': colors.default,
    '--openfga-dark-accent': colors.green
  };
  return <div className="openfga-code-viewer" style={themeStyle}>
      {title && <div className="openfga-code-viewer__title">{title}</div>}
      <div className="openfga-code-viewer__code" data-language="dsl">
        {tokens.map((t, i) => <span className="openfga-code-token" data-token={t.type || 'default'} key={i} style={{
    '--openfga-dark-token-color': t.color || colors.default
  }}>
            {t.text}
          </span>)}
      </div>
    </div>;
};

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

<OpenFGACodeBlock
  code={`type user

type team
\x20 relations
\x20   define member: [user]

type project
\x20 relations
\x20   define team: [team]
\x20   define can_view: member from team
\x20   define can_edit: member from team

type document
\x20 relations
\x20   define project: [project]
\x20   define can_view: can_view from project
\x20   define can_edit: can_edit from project`}
/>

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.

## Related reading

* [Running OpenFGA in production](/docs/best-practices/running-in-production)
* [Source of truth](/docs/best-practices/source-of-truth)
* [Multi-tenant SaaS](/docs/use-cases/multi-tenant-saas)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.