cd /news/developer-tools/building-oasis-a-systems-theory-appr… · home › topics › developer-tools › article
[ARTICLE · art-144417] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Building OASIS: A Systems Theory Approach to Multi-Tenant SaaS Architecture

A developer designed OASIS (Opinionated Architecture for Secure Isolated SaaS), a Go and Nuxt 3 framework that enforces multi-tenant data isolation structurally rather than through developer discipline. The system injects a tenant-scoped PostgreSQL search_path and Ent ORM transaction into the request's context.Context, so handlers run standard single-tenant CRUD code while being unable to query the wrong tenant, and it uses Casbin with a Redis watcher for distributed, domain-scoped authorization across Docker nodes.

by read4 min views1 publishedOct 3, 2026

How to engineer a modular SaaS framework in Go and Nuxt 3 that abstracts multi-tenant complexity for junior developers.

Building a multi-tenant SaaS typically introduces a severe cognitive burden on development teams. The moment you mix multiple clients into a single database, you rely on behavioural discipline—hoping a junior developer never forgets a WHERE tenant_id = ? clause.

To solve this, I designed OASIS (O pinionated A rchitecture for S ecure I solated S aaS). OASIS shifts data isolation from a behavioural requirement to a structural constraint. By applying systems theory principles (specifically Donella Meadows’ framework of stocks, flows, and feedback loops), we can analyse how this architecture provides the security of isolated multi-tenancy while preserving the developer experience (DevEx) of a single-tenant CRUD application.

Here is a technical breakdown of the OASIS framework and the systemic reasoning behind it.

The framework is built on a highly opinionated tech stack, structured into distinct subsystems:

ent-casbin adapter, casbin-redis-watcher). To understand how OASIS abstracts complexity, we must map how resources and information flow through the system.

tenant_01h45...). Each tenant is a completely separate namespace within a single PostgreSQL instance.database/sql connection pool. Managing this stock efficiently is critical to preventing noisy-neighbour exhaustion. The defining flow of OASIS is the Go context.Context. It acts as the immutable carrier of identity.

When a request hits the Go backend, middleware extracts the JWT and the tenant subdomain. It then injects this identity into the context.Context and passes it down the chain. The handler business logic never needs to inspect the HTTP request headers directly.

By cross-referencing these subsystems, we can identify powerful synergies that eliminate developer friction and prevent systemic failures.

The highest risk in multi-tenancy is data leakage. OASIS mitigates this by injecting a database transaction bound to a specific search_path directly into the request flow.

When a request arrives, the Go middleware acquires a connection from the global pool, executes SET LOCAL search_path TO tenant_x, starts an Ent ORM transaction (*ent.Tx), and attaches it to the context.Context.

To the junior developer, the code looks like standard single-tenant CRUD logic:

go
func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
    // rbac.Can natively reads the Casbin identity from the context flow
    if !rbac.Can(r.Context(), "GET", "/api/users") {
        http.Error(w, "Forbidden", http.StatusForbidden)
        return
    }

    // fetchTx extracts the already-isolated Ent transaction
    tx := fetchTx(r.Context())
    users, _ := tx.User.Query().All(r.Context())

    renderJSON(w, users)
}

Because the search_path is tied to the transaction, it automatically resets on commit or rollback. Connection pool poisoning is impossible, and developers are structurally incapable of querying the wrong tenant.
Resource Cascades: Nuxt 3 Host Routeing

Instead of maintaining three separate repositories for the marketing site, global admin panel, and tenant apps, OASIS utilises a resource cascade at the SSR layer.

A single Nuxt 3 application parses the incoming Host header. Caddy dynamically routes *.saasdomain.tld, and Nuxt's server middleware intercepts it. The host identity cascades down to the Vue components, dynamically mounting the correct layouts and executing Zod-validated state injections (useAuth and useRBAC) without URL parameter clutter.
Reinforcing Loops: Distributed Authorisation

For authorisation, OASIS uses Casbin with domain-scoped roles g(user, role, domain). However, a stateless Go backend deployed across multiple Docker containers creates a stale-cache problem.

To create a reinforcing synchronisation loop, OASIS integrates casbin-redis-watcher.

    An admin updates a policy on Node A.

    Node A writes the rule to the global public.casbin_rule PostgreSQL table.

    Node A publishes a Redis Pub/Sub ping.

    Nodes B, C, and D intercept the flow, instantly re their in-memory Casbin graphs from the database.

The system self-heals its security posture across the entire cluster in milliseconds.
Licensing as a System Boundary (BUSL-1.1)

Finally, protecting the framework itself requires a legal boundary. OASIS uses the Business Source Licence (BUSL-1.1) (often referred to as Fair Source).

Under BUSL-1.1, the code is public and completely free for hobbyists, learners, and startups. The Additional Use Grant explicitly permits commercial production use, provided the entity's gross revenue is under £1,000,000 GBP.

This creates a mutualistic loop: junior developers get unfettered access to enterprise-grade architectural tooling to learn the trade, while massive corporations are prevented from exploiting the framework without purchasing a commercial licence. After four years, each release automatically converts to a permissive Apache 2.0 licence, ensuring the code eventually benefits the wider open-source ecosystem permanently.

By treating multi-tenancy as a systemic architecture problem rather than a behavioural coding standard, OASIS provides a bulletproof foundation. The complexity remains beneath the surface, allowing developers to do what they do best: ship features.
── more in #developer-tools 4 stories · sorted by recency
── more on @oasis 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/building-oasis-a-sys…] indexed:0 read:4min 2026-10-03 · —