OpenFGA, natively in PostgreSQL: a zero-dependency PL/pgSQL engine that answers OpenFGA authorization queries inside the database that already holds your application's data.
Zero-dependency means installation is running SQL scripts against a database you can already connect to — self-hosted, RDS, Aurora, Cloud SQL — without a superuser, a filesystem, or a restart. CEL condition support comes from cel4postgres, itself pure SQL, vendored into the install.
PostgreSQL 18 or newer. Engine-generated store and model ids are
native uuidv7(), used without a compatibility shim.
The id domain is uuid. Object and subject ids are native
uuids, accepted in canonical lower-case hyphenated spelling only,
where upstream OpenFGA accepts nearly arbitrary strings. This is a
deliberate, documented divergence in the safe (refusing) direction,
in exchange for native uuid storage, indexes, and joins against
your application's own tables.
Status: v1 surface complete, pre-release. The engine is built and verified against a pinned conformance target, openfga/openfga v1.19.0: the upstream YAML corpus and upstream's own imported test runners run green differentially against the live pinned server, and every knowing divergence is measured, pinned from both sides, and documented in docs/CONFORMANCE.md.
check(includingbatch_check),expand,list_objects,list_userswrite_authorization_model— whole-model, upstream JSON shape, immutable and versioned- Tuple
write/deletewith upstream error semantics (includingon_duplicate/on_missing), andreadwith keyset pagination - A minimal store namespace (
create_store/delete_store)
Distribution is plain SQL scripts and pg_tle, both first-class — see docs/INSTALL.md.
From a release, one file installs everything:
psql -v ON_ERROR_STOP=1 -f fga4postgres--<version>.sql "$DB_URL"From a checkout:
psql -v ON_ERROR_STOP=1 -f vendor/cel4postgres--*.sql "$DB_URL"
for f in sql/*.sql; do
psql -v ON_ERROR_STOP=1 -f "$f" "$DB_URL"
doneThe scripts are idempotent; re-running the installer is the upgrade path. docs/INSTALL.md covers the pg_tle channel and the consumer privilege template.
Requirements: Docker with the compose plugin, and Go for running the test suite from the host (optional — see the containerised runner below).
cp .env.example .env # optional; every variable has a default
docker compose up -d --waitThis brings up two disposable services:
- postgres — pinned
postgres:18-alpinewithPGDATAon a tmpfs. On every start, initdb re-runsdocker/000_install.sh, which applies the vendored cel4postgres bundle and then everything insql/, so installing the schema is part of bringing the database up.--waitreturns only whencel.version()andfga.version()answer — healthy means installed, not merely listening. - openfga — the reference OpenFGA server, pinned at v1.19.0, used as the conformance oracle. The memory datastore makes a restart a reset.
Because the data directory is a tmpfs, docker compose down discards
the database entirely; there is no volume to clean up and no way for a
stale schema to survive into a test run.
Verify the stack:
psql "postgres://fga:password@localhost:5432/fga" \
-c "SELECT cel.version(), fga.version()"
curl -fsS http://localhost:8080/healthzIf a port is taken on your machine, set POSTGRES_PORT,
OPENFGA_HTTP_PORT, or OPENFGA_GRPC_PORT in .env.
Run the tests:
go test ./... # from the host
docker compose run --rm test # containerised, no host Go neededSee CLAUDE.md for the project's design decisions, conformance policy,
and conventions.
Apache License 2.0 — see LICENSE.