Building Melange: Zanzibar‑Style Auth Without a Separate…
    Neura MarketNeura Market/DeepSeek
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityTrending
    DeepSeekBlogBuilding Melange: Zanzibar‑Style Auth Without a Separate Service
    Back to Blog
    Building Melange: Zanzibar‑Style Auth Without a Separate Service
    architecture

    Building Melange: Zanzibar‑Style Auth Without a Separate Service

    Patt-tom McDonnell March 15, 2026
    0 views

    Over the holidays, I finally had some time to breathe and dive into a few "itch-to-scratch" side...


    title: Building Melange: Zanzibar‑Style Auth Without a Separate Service published: true date: 2026-01-13 05:11:00 UTC tags: canonical_url: https://pthm.dev/introducing-melange/

    Over the holidays, I finally had some time to breathe and dive into a few "itch-to-scratch" side projects. A fresh repo, a blank README, and the rapid-fire implementation of core features. But like clockwork, I hit the same wall I’ve hit in every project for the last decade.

    I had to deal with Authorization.

    Authentication

    We often lump "Auth" into one bucket, for good reason; they're close cousins, but they are two very different beasts.

    Authentication (Authn) is about identity: Who are you? it's usually one of the first problems you solve, I have built more authentication systems than I have built full apps or products. Most unfinished apps have a functioning authentication system. Today, this is essentially a solved problem.

    Whether you use a managed provider or a solid library, the path is well-trodden. You set up a login form, handle a session, maybe add 2FA, and you’re done.

    The interesting thing about Authn is that it doesn’t really grow with your app. Whether you have ten users or ten million, the "login" logic remains largely the same.

    Authorization

    Authorization (Authz) is the opposite. It’s about permissions: What are you allowed to do?

    In the beginning, Authz is deceptively simple. Let’s look at a standard GitHub-style model:

    • Users belong to Orgs.
    • Repos belong to Orgs.
    • Members of an Org can contribute to its Repos.

    In your database, that looks like five tables: users, orgs, repos, and the join tables org_users and org_repos.

    Imagine an API route to update a repository: PUT /repos/:id. You have an authenticated user ID (user_id = 'X') and a repository ID (repo_id = 'Y'). You need to ask: Can User X modify Repository Y?

    To answer that, you have to verify the chain of ownership:

    1. Which Org owns this Repo?
    2. Is the User a member of that Org?

    In SQL, it starts out manageable:

    SELECT 1 FROM repos r
    JOIN org\_repos or ON r.id = or.repo\_id
    JOIN org\_users ou ON or.org\_id = ou.org\_id
    WHERE r.id = 'Y' AND ou.user\_id = 'X';
    
    

    A relatively simple query that joins through the ownership chain. It works fine for five tables. But real-world requirements never stay simple.

    Growing Pains

    You add Issues. Issues belong to Repos. Now, to check if a user can edit an issue, you’re joining issues -> repos -> org_repos -> org_users.

    What if an Org has Teams? And Teams can be nested? Now you aren't just checking if a user is in an Org; you're checking if they are in a Team, or a Sub-Team, that has a specific role on a Repo.

    Suddenly, you are writing more code to authorize the request than you are to perform the actual business logic. Your queries look like this:

    -- Checking permission via nested teams and direct grants
    SELECT 1 FROM permissions p
    LEFT JOIN team\_members tm ON p.accessor\_id = tm.team\_id
    WHERE p.resource\_id = 'repo\_123'
    AND (p.user\_id = 'user\_abc' OR tm.user\_id = 'user\_abc')
    AND p.capability = 'write';
    
    

    This is Relationship-Based Access Control (ReBAC), and doing it manually in SQL or in your application code can be cumbersome and error-prone.

    The Light at the End of the Tunnel

    There are a number of solutions to this problem, and a plethora of services you can run or buy that aim to provide a way of answering these questions for you.

    A large portion of these systems are based off a paper published by Google, "Zanzibar: Google’s Consistent, Global Authorization System".

    These systems treat your permissions as a graph. They ignore your database tables and look at "tuples", simple strings that define relationships:user:alice is member of org:acme``repo:engine is child of org:acme

    A few notable examples of these Zanzibar or Zanzibar-like systems are:

    • OpenFGA
    • SpiceDB
    • Keto

    For the rest of this post I will be talking about OpenFGA.

    OpenFGA is an open-source implementation of Zanzibar (donated to the CNCF by Okta/Auth0).

    OpenFGA provides a Domain Specific Language (DSL) to model your authorization rules. But it has a high "Entry Fee." Because OpenFGA is a separate service, you face a Synchronization Problem : every time you update your database, you must also update the OpenFGA tuples via an API call. If one fails, your permissions are out of sync.

    RoverApp - Pure Postgres ReBAC

    I was searching for a middle ground when I found a brilliant post by the team at Rover. They loved the OpenFGA model but hated the sync overhead. Their solution was to implement OpenFGA in Postgres. pgfga.

    Rover’s approach was elegant in its simplicity:

    1. The Model Table: They created an authz_model table to store the OpenFGA schema directly in Postgres.
    2. Dynamic Tuples (The Secret Sauce): Instead of a static table of tuples that you have to sync, they used Database Views. They mapped their existing domain tables (like org_users) into a view that "looks" like an OpenFGA tuple table. Melange reads tuples from a melange_tuples view you define over your existing tables.
    3. The Generic Check: They wrote a recursive PL/pgSQL function—check_permission(user, relation, object)—that traverses these views to find a path between the user and the resource.

    This was a game-changer. It meant you could use the power of OpenFGA's modeling while keeping everything "Always-In-Sync" within a single Postgres transaction.

    Melange

    I took the Rover solution and ran with it, but I eventually hit a ceiling.

    The Rover implementation relies on a generalized, recursive function. That’s fine for simpler models, but once I pushed on wildcards (public access) and tuple-to-userset (TTU) chains, the generic interpreter became the hot path.

    I got nerd-sniped. I spent the holiday implementing the full spec, but I chose a different architecture: Melange is a compiler. It reads your OpenFGA schema and generates specialized PostgreSQL functions tailored to your relationship graph.

    How it works:
    melange migrate parses your OpenFGA schema and generates relation-specific SQL functions (plus a dispatcher). Those functions query a melange_tuples view you define over domain tables, with compile-time-inlined role closure and TTU traversal paths. Runtime checks are pure SQL, so there’s no external service or tuple sync.

    1. Specialized Dispatching

    Here’s a tiny TTU model from the official test suite:

    type folder
      relations
        define viewer: [user]
    
    type document
      relations
        define parent: [folder]
        define viewer: viewer from parent
    
    

    Melange generates a dedicated check_document_viewer(...) function plus a dispatcher. The generated SQL includes an explicit TTU edge:

    -- Recursive access path via parent -> viewer
    IF EXISTS (
    SELECT 1
    FROM melange\_tuples AS link
    WHERE link.object\_type = 'document'
    AND link.relation = 'parent'
    AND check\_permission\_internal(
    p\_subject\_type, p\_subject\_id,
    'viewer',
    link.subject\_type, link.subject\_id,
    p\_visited || v\_key
    ) = 1
    ) THEN
    RETURN 1;
    END IF;
    
    

    The entry point stays small and fast: check_permission(...) simply routes to check_document_viewer(...), check_folder_viewer(...), and so on. Because those functions are generated for your schema, they follow the precomputed paths through the relationship graph. PostgreSQL can plan the joins and indexes ahead of time.

    2. List Queries Are First-Class

    Real apps need more than binary checks. You often need to populate UI lists with what a user can actually see. Melange generates set-returning functions for this:

    • Object Filtering: "Which documents can User X view?"
    • Subject Filtering: "Which users can view Document Y?"

    Under the hood, you get functions like list_document_viewer_objects(...) and list_document_viewer_subjects(...), routed through list_accessible_objects(...) and list_accessible_subjects(...). They’re joinable straight into your application queries. Recent versions also add cursor-based pagination for these list APIs.

    3. Performance & Compatibility

    Moving from interpretation to compilation pays off.

    • Low-latency checks: Local benchmarks are often sub‑millisecond once the database cache is warm. Network latency between your app and your database is a bigger overhead than the authorization logic itself.
    • Schema 1.1 compatibility: Melange is validated against the OpenFGA test suite and supports the full 1.1 executable spec (excluding conditions).

    Melange is built for the "Middle Phase." Most of us aren't Google, and we don’t need a globally distributed auth cluster on Day 1. We need something flexible enough to grow, but simple enough to live with. If you truly need multi-region or cross-database authorization later, the standard OpenFGA schema keeps your migration path open.

    Melange gives you the modeling power of OpenFGA with the reliability and consistency of in-transaction SQL. It’s designed to carry you from your first user until the day you’re actually big enough to need a dedicated Zanzibar cluster.

    Melange is open source and available on GitHub, with docs at melange.sh.

    Tags

    architecturesecurityshowdevsideprojects

    Comments

    More Blog

    View all
    Five Gemma-4 models, one accelerator: what porting E2B 31B to AWS Inferentia2 taught megemma

    Five Gemma-4 models, one accelerator: what porting E2B 31B to AWS Inferentia2 taught me

    I ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...

    X
    xbill
    Hey DEV, I'm Tobore. Let's actually connect.community

    Hey DEV, I'm Tobore. Let's actually connect.

    Hey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...

    L
    Laurina Ayarah
    I burned through thousands of AI tokens. Then a friend did it for freeai

    I burned through thousands of AI tokens. Then a friend did it for free

    (yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...

    P
    Paulo Henrique
    Claude might be saturating your machineai

    Claude might be saturating your machine

    My laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...

    S
    Sidhant Panda
    Automated GitHub Code Reviews Using Google Geminigithubactions

    Automated GitHub Code Reviews Using Google Gemini

    I Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...

    D
    Darren "Dazbo" Lester
    What is an "agentic harness," actually?ai

    What is an "agentic harness," actually?

    I've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...

    T
    Tilde A. Thurium

    Stay up to date

    Get the latest DeepSeek prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for DeepSeek and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this DeepSeek resource

    • Building a RAG Chatbot for Movie Recommendations with Qdrant and OpenAIn8n · $14.99 · Related topic
    • Compose/Stitch Separate Images Together Using n8n & Gemini AI Image Editingn8n · $14.99 · Related topic
    • Provide Real-time Updates for Notion Databases via Webhooks with Supabasen8n · $14.99 · Related topic
    • NPR Station Finder Service MCP Servern8n · $4.99 · Related topic
    Browse all workflows