Your First Migration
With your schema and tuples view in place, the next step is compiling the authorization model into PostgreSQL functions.
Validate Your Schema
Check that your schema is syntactically valid before migrating:
melange validateThis parses the .fga file and reports syntax errors or cyclic dependencies. It does not require database access.
Apply the Migration
melange migrateThis connects to your database (using the URL from your config file or --db flag), compiles your schema, and installs the generated SQL functions.
You’ll see output like:
Migrating schema...
✓ Compiled 6 functions
✓ Installed check_permission dispatcher
✓ Installed list_accessible_objects
✓ Installed list_accessible_subjects
Migration complete.Preview Without Applying
To see the generated SQL without making any changes:
melange migrate --dry-runThis outputs the full SQL that would be executed, which is useful for review or debugging.
Verify the Setup
Check Migration Status
melange statusReports whether a migration has been applied and if the schema has changed since the last migration.
Run Health Checks
melange doctorThe doctor command runs these checks against your database:
- Schema File: exists, parses correctly, no cyclic dependencies
- Migration State:
melange_migrationstable exists, schema is in sync - Generated Functions: dispatcher and per-relation functions are present, no orphans
- Tuples Source:
melange_tuplesview exists with the correct columns - Data Health: tuple count, type/relation validation against schema
- Performance: view analysis (UNION ALL usage, missing expression indexes)
For detailed output:
melange doctor --verboseTest a Permission Check
Run a permission check to confirm the setup:
SELECT check_permission('user', 'alice', 'can_read', 'repository', '42');
-- Returns 1 (allowed) or 0 (denied)If this returns 0 and you expect 1, check that:
- The
melange_tuplesview returns the expected rows (SELECT * FROM melange_tuples WHERE subject_id = 'alice') - The relation names in your view match your schema exactly
Generate Client Code (Optional)
If you configured client code generation during melange init, generate the type-safe helpers:
melange generate clientThis creates files in your output directory (e.g., internal/authz/) with constants and constructors:
import "myapp/internal/authz"
allowed, err := checker.Check(ctx,
authz.User("alice"),
authz.RelCanRead,
authz.Repository("42"),
)Regenerate after any schema change to keep the generated code in sync.
Using an External Migration Framework
If you chose the versioned migration strategy during init (or prefer to use golang-migrate, Atlas, Flyway, etc.), generate SQL files instead:
melange generate migrationThis produces timestamped migration files in your output directory:
migrations/
├── 20240315120000_melange.up.sql
└── 20240315120000_melange.down.sqlApply them with your framework. See Running Migrations for comparison modes and CI workflows.
Next Steps
- Checking Permissions: Checker API, caching, bulk checks, decision overrides, error handling
- Listing Objects: find all objects a user can access
- Listing Subjects: find all users with access to an object
- How It Works: the compiler model and generated SQL
- SQL API Reference: calling permission functions directly from any language
- CLI Reference: full command and flag documentation