Self-hosted service
openfga/openfga avatar
openfga/openfga

OpenFGA: a Zanzibar-style authorization engine you run yourself

A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar

5,899 stars511 forksGoApache-2.0

At a glance

What is it?
OpenFGA models permissions as relationships and answers check calls over HTTP or gRPC. It is a good fit for teams outgrowing role tables, and a poor fit for anyone who wants a complete identity product.
Who is it for?
Adopt OpenFGA if your permission rules have outgrown a roles table and you are willing to operate one more stateful service, with Postgres or MySQL behind it rather than the in-memory engine. Do not adopt it as a replacement for an identity provider: it decides what a subject may do, not who that subject is.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What OpenFGA decides, and what it deliberately does not

OpenFGA is an authorization engine. You give it a model of your objects and the relationships between them, and it answers questions of the form "does this user have this relation to this object". The README describes it as "a high-performance, flexible authorization/permission engine inspired by Google Zanzibar", and the repository topics list rbac, abac, rebac and fga, which is the range of permission styles it is meant to cover. The unit of work is a check, not a login.

That boundary matters more than any feature list. OpenFGA does not authenticate anyone, does not issue tokens, and does not store user profiles. Something else has to establish who the caller is; OpenFGA then decides what that caller can reach. Teams that arrive expecting an identity provider will find half a product. Teams that already have authentication and are fighting a growing table of roles and exceptions are the intended audience.

The repository layout supports that reading. There is a cmd directory holding the binary entry point, an internal directory, a pkg directory, a plans directory, and a tests directory, which is the shape of a server project rather than a library-first toolkit. The Go module path is github.com/openfga/openfga, and the README notes the engine "Can also be embedded as a Go library" with a link to the server package example. So the same code can run as a standalone service or inside a Go process, but the service is the primary form.

Relationship tuples, not role columns

The mechanism is a store of relationship tuples plus an authorization model that says how those tuples combine. A tuple records that a subject has a relation to an object. The model defines the object types, the relations, and the rules that let a relation be satisfied indirectly, for example through a parent object or through another relation. A check call then walks that graph instead of evaluating a policy expression.

This is why the project is described as ReBAC rather than RBAC. In a role table you store the role on the user and hope the mapping to resources stays stable. Here you store the edge, and the model decides what the edge implies. Changing what a role means is a model change, not a data migration across every user row.

The engine exposes both HTTP and gRPC. The README lists "High-performance, developer-friendly APIs (HTTP & gRPC)" as a highlight, and the docker-compose file maps port 8080 for HTTP, 8081 for gRPC, 3000 for the playground and 2112 for Prometheus metrics. The Dockerfile exposes 8081, 8080 and 3000 and ships a grpc-health-probe binary, with a healthcheck pointed at port 8081. If you run the container under an orchestrator, that probe is the readiness signal to wire up.

Storage sits behind an interface. The README lists In-Memory, PostgreSQL, MySQL, and SQLite as beta. The choice is not cosmetic: the quickstart warns that with the default in-memory engine "data is ephemeral and will be discarded once the service stops".

Installing OpenFGA and running a first check

The README offers several installation paths: Docker, Docker Compose, Homebrew, precompiled binaries, and building from source. The fastest way to see the API is the published image with in-memory storage, which the README explicitly marks as not for production.

bash
docker run -p 8080:8080 -p 3000:3000 openfga/openfga run

This starts the server with HTTP on 8080 and the playground on 3000. Port 3000 is the browser UI for writing a model and trying checks against it, which is the quickest way to find out whether the tuple model matches how your application actually thinks about permissions.

With the server up, the README's next step creates a store. A store is the container for models and tuples, so it is the first object you need before anything else can be written.

bash
curl -X POST 'localhost:8080/stores' \
  --header 'Content-Type: application/json' \
  --data-raw '{"name": "openfga-demo"}'

The response contains a store identifier that later calls use. From there you write an authorization model and then tuples, both through the same HTTP API, and the CLI in the openfga/cli repository is the more comfortable route for that work. The README points to it for "interacting with an OpenFGA server and testing authorization models".

If you want Postgres rather than memory, the repository's docker-compose.yaml is the reference. It defines a postgres service, a migrate service that runs the migration before the server starts, and the openfga service itself, with the datastore configured through environment variables.

yaml
environment:
  - OPENFGA_DATASTORE_ENGINE=postgres
  - OPENFGA_DATASTORE_URI=postgres://postgres:password@postgres:5432/postgres?sslmode=disable
  - OPENFGA_DATASTORE_MAX_OPEN_CONNS=100 #see postgres container
  - OPENFGA_PLAYGROUND_ENABLED=true

The migrate service matters. It depends on Postgres being healthy and the server depends on the migration completing, so the schema is applied before the API accepts traffic. Running the server against an empty database without that step is the most likely first failure.

The limitations the README admits to

The README carries a Limitations section, and it is worth reading before you design around the project rather than after. Google Zanzibar as described in the paper has a set of capabilities; an open source reimplementation rarely has all of them, and the project does not claim otherwise.

The more concrete constraint is storage. SQLite is labelled beta, which means the two engines to take seriously in production are PostgreSQL and MySQL. That is a real operational commitment: a stateful database that must be migrated, backed up and kept available, because every authorization check depends on it. An application that previously answered permission questions from its own tables now has a network hop in the critical path of every request that needs a decision.

The in-memory engine is a trap if you skim. It is the default, it is what the quickstart uses, and it discards everything when the process stops. It is fine for evaluation and for tests. It is not a cache you can promote to production by adding replicas, because each process would hold its own copy of the tuples.

There is also a scope limit worth stating plainly: OpenFGA decides permissions, so it cannot tell you whether a user should be allowed to log in, whether a token is valid, or whether an account is suspended. Those questions stay in your identity layer. If your actual problem is single sign-on, this is the wrong tool and no amount of modelling will fix that.

OpenFGA against Keycloak, OPA and SpiceDB

The comparison people search for most is OpenFGA versus Keycloak, and the two are not substitutes. Keycloak is an identity and access management server: it authenticates users, issues tokens and supports federation protocols. OpenFGA authenticates nobody. It is the piece you add when Keycloak has told you who the user is and you still need to know which of ten thousand documents they may open. Using both is normal; choosing between them is a category error.

Open Policy Agent takes a different route to the same question. OPA evaluates policies written in Rego against input documents you supply, so the decision logic is code you write and the data is whatever you hand it. OpenFGA stores the relationships itself and derives the answer from the model plus the tuple graph. If your rules are naturally expressed as relationships between objects, the tuple store removes a lot of glue. If your rules are mostly attribute arithmetic over a request payload, a policy engine fits better.

SpiceDB is the closest conceptual neighbour: another Zanzibar-inspired permission system with its own schema language. The difference is in the surrounding decisions rather than the idea. OpenFGA's README points at SDKs for Java, Node.js, Go, Python and .NET, a Terraform provider, a CLI, a playground, and adoption by Auth0, Grafana Labs, Canonical, Docker, Agicap and Read.AI. If your team already lives in that tooling, the integration work is smaller.

Licence, releases and the cost of staying current

OpenFGA is licensed under Apache-2.0. That is a permissive licence, and it is the same family as much of the surrounding infrastructure, which keeps licence review short. It is not legal advice; if you redistribute the software or embed it in a product, your own counsel should confirm the obligations, including the notice and attribution requirements that come with the licence.

The repository shows a steady release cadence: v1.21.0 on 2026-09-20, v1.20.0 on 2026-09-08 and v1.19.0 on 2026-08-25, with the last push on 2026-09-21. A CHANGELOG.md and a RELEASES.md sit at the top level, so the upgrade surface is documented rather than implied. The practical upgrade cost is the schema: the compose file runs a separate migrate command before the server starts, which tells you that datastore migrations are part of the release process and not something the server does quietly on boot. Budget for running that migration as a deliberate step, with a backup taken first.

Building from source is heavier than it looks. The go.mod pins go 1.25.7 with toolchain go1.26.8, and the Dockerfile builds from a Chainguard Go image with CGO disabled, then copies the binary into a static Chainguard image. The dependency list is long and includes the OpenFGA API proto module and the OpenFGA language package, so the build pulls in the modelling language as well as the server.

Editorial conclusion

Adopt OpenFGA if your permission rules have outgrown a roles table and you are willing to operate one more stateful service, with Postgres or MySQL behind it rather than the in-memory engine. Do not adopt it as a replacement for an identity provider: it decides what a subject may do, not who that subject is. Before committing, verify that the datastore you intend to run is the one the migration command supports, and read the limitations section of the README rather than assuming every Zanzibar feature is present.

Frequently asked questions

What is OpenFGA used for?

It answers fine-grained authorization questions: given a subject and an object, does this relation hold. Applications use it to replace or extend role tables with relationship-based permissions, and the README lists adoption by Auth0, Grafana Labs, Canonical, Docker, Agicap and Read.AI.

Is OpenFGA a ReBAC system?

Yes. The README describes it as inspired by Google Zanzibar, and the repository topics include rebac alongside rbac, abac and fga. Permissions are stored as relationship tuples and resolved through an authorization model rather than through role columns on a user record.

Is OpenFGA production ready?

The project ships a Production Readiness section and points to a Running in Production guide, and the quickstart explicitly marks the in-memory setup as not for production. In practice that means running PostgreSQL or MySQL behind it and treating the in-memory engine as evaluation only.

Is OpenFGA free and open source?

It is open source under the Apache-2.0 licence, and the source lives in the openfga/openfga repository on GitHub. The README also links a hosted offering at fga.dev, so there is a commercial option alongside the self-hosted engine.

How is OpenFGA different from Open Policy Agent?

OpenFGA stores relationships itself and derives answers from a model plus the tuple graph, while OPA evaluates policies you write against input you supply. If your rules are naturally relationships between objects, the tuple store removes glue code; if they are attribute arithmetic over a request, a policy engine fits better.

How does OpenFGA work?

You define an authorization model describing object types and relations, write relationship tuples into a store, and the engine resolves a check by walking that graph. The server exposes the API over both HTTP and gRPC, with storage in memory, PostgreSQL or MySQL.

Official sources

  1. License: Apache-2.0
  2. openfga/openfga on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openfga-openfga.svg)](https://hysenlabs.com/projects/openfga-openfga)