What it is

OpenFGA implements Relationship-based Access Control (ReBAC) from Google’s Zanzibar paper. Permissions are derived from relationships between users, groups, and resources — authorization logic lives outside application code.

OpenFGA Server = database server
Store          = individual database (model + tuples)

Core syntax

Tuple format: object:id#relation@user:id

document:roadmap#viewer@user:alice          // direct user
document:roadmap#viewer@group:eng#member    // all members of a group

# operator: group#member means “anyone who has a member relationship with a group” — not the group entity itself. Without #, it’s ambiguous who in the group gets access.

Model patterns

type document
  relations
    define owner: [user]
    define editor: [user] or owner
    define viewer: [user, group#member] or editor or viewer from parent
  • or = union (either condition)
  • and = intersection (both required)
  • from parent = hierarchical inheritance

Authorization flow

Request → App DB lookup (what sets does this user/resource belong to?)
        → OpenFGA Check(user, relation, object) → { allowed: true/false }
        → Return data or 403

Docker setup

services:
  migrate:
    image: openfga/openfga:v1.11.5
    command: migrate     # run first
 
  openfga:
    image: openfga/openfga:v1.11.5
    command: run
    depends_on:
      migrate:
        condition: service_completed_successfully
    ports:
      - "8080:8080"      # HTTP API
      - "3000:3000"      # Playground UI (disable in prod)

Auth

Local dev: disable auth entirely. Production: preshared key via OPENFGA_AUTHN_PRESHARED_KEYS.

Warning

Store OPENFGA_AUTHN_PRESHARED_KEYS in Kubernetes Secrets — never commit auth keys to code.

Production notes

Warning

Production checklist — use PostgreSQL (not SQLite), network-isolate the server, cache Check results client-side, and clean up tuples on deletion (stale tuples accumulate silently).

See also