Skip to main content
Gemini Generated Image O054xko054xko054 Removebg Preview Melange is a Go library for implementing Fine Grained Authorization / ReBAC (Relationship Based Access Control), it implements parts of OpenFGA in Postgres using functions and a accompanying toolchain and runtime library for Go.
Melange is not associated with OpenFGA and is not an official implementation of their specification or protocols.
Melange builds on ideas from several important projects and research efforts in the fine-grained authorization and Relationship-Based Access Control (ReBAC) ecosystem.

pgfga (rover-app)

Melange is most directly inspired by pgfga, a TypeScript-focused project created by the rover-app team. pgfga experiments with implementing ReBAC semantics directly inside PostgreSQL, using SQL functions and data structures rather than a separate authorization server. you can read about their version in their blog post Melange adopts this philosophy, while adapting it to the Go ecosystem.

OpenFGA

OpenFGA is an open-source authorization engine inspired by Zanzibar. It provides a schema language, tuple APIs, and a graph evaluation model that allow developers to define and query ReBAC relationships. Melange like pgfga is compatible with the OpenFGA modeling language (DSL). It uses the same schema syntax to define relationships, types, and authorization rules. Melange uses the OpenFGA DSL and parser for:
  • defining object types and relations
  • expressing permission derivations and inheritance rules
  • modeling membership, ownership, and delegation semantics

Zanzibar and ReBAC Foundations

The conceptual foundation for Melange originates in Zanzibar-style authorization systems, first described in Google’s Zanzibar: Google’s Consistent, Global Authorization System paper.

How Melange Is Different

Melange takes inspiration from Zanzibar-style authorization and OpenFGA’s modeling approach, but it follows a fundamentally different architectural philosophy. Instead of running authorization as a separate networked service with its own datastore, Melange evaluates permissions directly inside PostgreSQL and integrates natively into Go applications. In many systems, authorization data already exists in the database — through foreign keys, membership tables, ownership relationships, and hierarchical resources. Traditional FGA deployments require duplicating that state into a separate service, keeping two databases in sync, and managing additional operational infrastructure. Melange avoids that problem by treating the database itself as the authorization engine. With Melange:
  • Authorization logic is co-located with application data, meaning writes, deletes, and cascading behavior stay consistent without manual synchronization.
  • Relationship tuples are derived from real schema relationships, instead of being stored and maintained separately.
  • Permission checks run inside Postgres using SQL functions, reducing latency and eliminating remote calls.
  • Application workflows, migrations, deletes, and referential integrity behave exactly as your database already intends.

Code Generation

Melange includes a small code generator that turns your OpenFGA-style schema into a type-safe Go API. Instead of sprinkling raw strings like "repository" or "can_read" throughout your code, you work with generated constants and helper functions that are aligned with your .fga model. Under the hood, Melange:
  • Parses your .fga schema using the official OpenFGA language parser
  • Walks the defined types and relations
  • Emits Go code that wraps melange.ObjectType, melange.Relation, and melange.Object in a strongly-typed, IDE-friendly API
You can run this via the CLI (melange generate) or programmatically via melange.GenerateGo.

What the Generator Produces

Given a schema with types like:
type user

type repository
  relations
    define can_read: [user]
    define owner: [user]
the generator produces:
  • Object type constants (backed by melange.ObjectType):
const (
	TypeUser       melange.ObjectType = "user"
	TypeRepository melange.ObjectType = "repository"
)
  • Relation constants (backed by melange.Relation):
const (
	RelCanRead melange.Relation = "can_read"
	RelOwner   melange.Relation = "owner"
)
  • Constructor functions for building melange.Object values:
// User creates a user object for relation checks.
func User(id string) melange.Object {
	return melange.Object{Type: TypeUser, ID: id}
}

// Repository creates a repository object for relation checks.
func Repository(id string) melange.Object {
	return melange.Object{Type: TypeRepository, ID: id}
}
  • Wildcard constructors for public / “any subject” patterns:
// AnyUser returns a wildcard user that matches user:* tuples.
func AnyUser() melange.Object {
	return melange.Object{Type: TypeUser, ID: "*"}
}
That lets your application code look like:
ok, err := checker.Check(ctx,
    authz.User(userID),
    authz.RelCanRead,
    authz.Repository(repoID),
)
You get compile-time safety, better autocomplete, and far fewer stringly-typed mistakes. Combined with the Postgres-native runtime, this makes Melange feel like a first-class part of your Go domain model, rather than a generic “stringy” auth layer bolted on the side.