Skip to content

Repository files navigation

fga4postgres

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.

v1 surface

  • check (including batch_check), expand, list_objects, list_users
  • write_authorization_model — whole-model, upstream JSON shape, immutable and versioned
  • Tuple write/delete with upstream error semantics (including on_duplicate/on_missing), and read with 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.

Installation

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"
done

The scripts are idempotent; re-running the installer is the upgrade path. docs/INSTALL.md covers the pg_tle channel and the consumer privilege template.

Development environment

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 --wait

This brings up two disposable services:

  • postgres — pinned postgres:18-alpine with PGDATA on a tmpfs. On every start, initdb re-runs docker/000_install.sh, which applies the vendored cel4postgres bundle and then everything in sql/, so installing the schema is part of bringing the database up. --wait returns only when cel.version() and fga.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/healthz

If 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 needed

See CLAUDE.md for the project's design decisions, conformance policy, and conventions.

License

Apache License 2.0 — see LICENSE.

About

OpenFGA, natively in Postgres: a zero-dependency PL/pgSQL OpenFGA-compatible engine.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages