Skip to content
Free and open source on GitHub

Zanzibar-Style Authorization for PostgreSQL

Fine-grained, relationship-based access control without an external service. Melange compiles OpenFGA schemas into SQL functions that run inside your existing database.

  • MIT licensed
  • PostgreSQL 14+
  • Go and TypeScript clients
  • SQL from any language

schema.fga

type repository
  relations
    define org: [organization]
    define admin: [user]
    define can_read: member from org or admin

Your application

SELECT check_permission(
  'user', 'alice', 'can_read', 'repository', '123'
);
-- 1: alice is a member of the repository's org

Features

Latest release

Melange v0.11.0

Run migrateBreakingSecurity fix FeaturesFixesPerformanceGenerated SQLGo runtimeTypeScriptCLIDocs

Melange v0.11.0 lets you choose which part of the generated SQL API a database gets, and adds per-relation accessible_* functions for filtering your own queries by access. Paged lists now do the work of one page, generated functions are planned once per session, and depth limits and cycles follow OpenFGA. It also fixes two ways a check or a migration could grant more than the model says.

  • Choose which relations and function families the SQL API installs, and filter your own queries with inlinable accessible_* functions
  • Paged lists read only the page: a first page of 50 contacts on the SaaS benchmark went from 3.5 s to 6 ms
  • Depth limits match OpenFGA, lists raise M2002 instead of truncating, and userset checks stop over-granting

How It Works

Melange is an authorization compiler. Like Protocol Buffers or GraphQL Code Generator, you define a schema and Melange generates optimized code tailored to your exact model. Instead of a generic runtime that interprets your model at query time, Melange generates purpose-built SQL functions for each relation in your schema. Role hierarchies are resolved at compile time and inlined into SQL, so runtime checks only recurse where your data does, such as nested parent folders.

schema.fga is compiled by melange migrate into PostgreSQL functions: check_permission(), list_accessible_objects() and list_accessible_subjects()schema.fgamelange migratePostgreSQL functionscheck_permission()list_accessible_objects()list_accessible_subjects()

Install

Install the CLI

The melange CLI is a single binary with no runtime dependencies, published for macOS, Linux, and Windows on amd64 and arm64. You only need PostgreSQL 14 or later when you run melange migrate.

brew install pthm/tap/melange

Step 1

Define Your Schema

Write your authorization model using the OpenFGA DSL. The same .fga files work with both Melange and OpenFGA, so there’s no vendor lock-in.

Melange supports direct assignments, computed usersets, unions, intersections, exclusions, tuple-to-userset, wildcards, userset references, and contextual tuples.

model
  schema 1.1

type user

type organization
  relations
    define owner: [user]
    define admin: [user] or owner
    define member: [user] or admin

type repository
  relations
    define org: [organization]
    define owner: [user]
    define admin: [user] or owner
    define can_read: member from org or admin
    define can_write: admin
    define can_delete: owner

Step 2

Query Your Existing Tables

Unlike traditional FGA systems, Melange doesn’t need a separate tuple store. Create a SQL view that maps your existing domain tables into tuples, and Melange queries them directly.

No data duplication. No sync jobs. Permissions are always consistent with your domain data, down to the current transaction.

CREATE VIEW melange_tuples AS
-- Organization memberships
SELECT
    'user' AS subject_type,
    user_id::text AS subject_id,
    role AS relation,
    'organization' AS object_type,
    organization_id::text AS object_id
FROM organization_members

UNION ALL

-- Repository ownership
SELECT
    'organization' AS subject_type,
    organization_id::text AS subject_id,
    'org' AS relation,
    'repository' AS object_type,
    id::text AS object_id
FROM repositories;

Step 3

Compile to SQL Functions

melange migrate compiles your schema into a PostgreSQL function per relation and installs them, along with check_permission and the list functions that dispatch to them.

Role hierarchies are flattened at compile time. can_read inherits from admin, which inherits from owner, so the generated function matches all three in a single lookup instead of walking the graph at query time. Run it in CI or a deploy step, or use melange generate migration to emit SQL files for your existing migration tool.

# Compile and install the functions
melange migrate

# Or emit up/down SQL for your migration tool
melange generate migration --output db/migrations

Step 4

Check Permissions From Any Language

Once compiled, permission checks are simple SQL function calls. Use the Go or TypeScript client libraries for convenience, or call the generated functions directly from any language that can talk to PostgreSQL.

checker := melange.NewChecker(db)

allowed, err := checker.Check(ctx,
    authz.User("alice"),
    authz.RelCanRead,
    authz.Repository("123"),
)

Studio

Inspect Everything in Studio

melange studio opens a local, read-only console on any melange database. See who can access what, explain any decision step by step, try a grant before you write it, and read the SQL generated for every relation. It needs only a database connection.

Studio's tuple browser showing the repositories user carol can access, with relation chips and an inline Explain Studio's tuple browser showing the repositories user carol can access, with relation chips and an inline Explain
An Explain trace showing why a user can read an issue An Explain trace showing why a user can read an issue
A Matrix result listing every repository relation as allowed or denied for a user on a repository A Matrix result listing every repository relation as allowed or denied for a user on a repository
A relation page with its definition, analysis and dependencies A relation page with its definition, analysis and dependencies
The Health page with melange doctor checks The Health page with melange doctor checks

Is Melange a Fit?

Good fit

An application backed by PostgreSQL that needs roles, sharing, teams, or folder-style hierarchies, and would rather not run and sync a separate authorization service.

Look elsewhere

Authorization shared across many services and databases, or attribute-based rules that need conditions.

Outgrow it? Move to OpenFGA

Your .fga files work unchanged in OpenFGA. Export your melange_tuples view as tuples and point your application at an OpenFGA server.

Coming from OpenFGA?

Keep your model, and replace the tuple store with a view over your tables.

Get started

Get Started in Minutes

Install the CLI, point it at your database, and check your first permission. The quick start takes you from an empty schema to a working check.

Terminal

# Initialize your project
melange init

# Apply schema and generate SQL functions
melange migrate

# Generate type-safe client code
melange generate client

# Inspect the database in a local web console
melange studio