<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: unexcitement</title>
    <description>The latest articles on DEV Community by unexcitement (@unexcitement).</description>
    <link>https://dev.to/unexcitement</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4143181%2F266a7db5-0062-4d92-8de6-8febe40dc505.jpg</url>
      <title>DEV Community: unexcitement</title>
      <link>https://dev.to/unexcitement</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unexcitement"/>
    <language>en</language>
    <item>
      <title>Building OASIS: A Systems Theory Approach to Multi-Tenant SaaS Architecture</title>
      <dc:creator>unexcitement</dc:creator>
      <pubDate>Sat, 03 Oct 2026 11:04:37 +0000</pubDate>
      <link>https://dev.to/unexcitement/building-oasis-a-systems-theory-approach-to-multi-tenant-saas-architecture-29b7</link>
      <guid>https://dev.to/unexcitement/building-oasis-a-systems-theory-approach-to-multi-tenant-saas-architecture-29b7</guid>
      <description>&lt;p&gt;How to engineer a modular SaaS framework in Go and Nuxt 3 that abstracts multi-tenant complexity for junior developers.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;WHERE tenant_id = ?&lt;/code&gt; clause. &lt;/p&gt;

&lt;p&gt;To solve this, I designed &lt;strong&gt;OASIS&lt;/strong&gt; (&lt;strong&gt;O&lt;/strong&gt;pinionated &lt;strong&gt;A&lt;/strong&gt;rchitecture for &lt;strong&gt;S&lt;/strong&gt;ecure &lt;strong&gt;I&lt;/strong&gt;solated &lt;strong&gt;S&lt;/strong&gt;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.&lt;/p&gt;

&lt;p&gt;Here is a technical breakdown of the OASIS framework and the systemic reasoning behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Subsystems (Nodes)
&lt;/h2&gt;

&lt;p&gt;The framework is built on a highly opinionated tech stack, structured into distinct subsystems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Ingress:&lt;/strong&gt; Caddy (Wildcard subdomains, On-Demand TLS, CORS-free local dev).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Frontend:&lt;/strong&gt; Nuxt 3 (TypeScript, SSR routeing via Host headers).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Backend:&lt;/strong&gt; Go (Lightweight concurrency, strict typing).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Persistence:&lt;/strong&gt; PostgreSQL (Isolated schemas) managed by the Ent ORM.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Authorisation:&lt;/strong&gt; Casbin (&lt;code&gt;ent-casbin&lt;/code&gt; adapter, &lt;code&gt;casbin-redis-watcher&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Orchestration:&lt;/strong&gt; OpenTofu, LXD, and Docker.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tracking Stocks and Flows
&lt;/h2&gt;

&lt;p&gt;To understand how OASIS abstracts complexity, we must map how resources and information flow through the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Core Stocks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Tenant Data (Intangible):&lt;/strong&gt; Walled off dynamically. Rather than row-level isolation (shared tables), OASIS uses &lt;strong&gt;Isolated Schemas&lt;/strong&gt; (&lt;code&gt;tenant_01h45...&lt;/code&gt;). Each tenant is a completely separate namespace within a single PostgreSQL instance.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Database Connections (Tangible):&lt;/strong&gt; Go maintains a single global &lt;code&gt;database/sql&lt;/code&gt; connection pool. Managing this stock efficiently is critical to preventing noisy-neighbour exhaustion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Context Flow
&lt;/h3&gt;

&lt;p&gt;The defining flow of OASIS is the Go &lt;code&gt;context.Context&lt;/code&gt;. It acts as the immutable carrier of identity. &lt;br&gt;
When a request hits the Go backend, middleware extracts the JWT and the tenant subdomain. It then injects this identity into the &lt;code&gt;context.Context&lt;/code&gt; and passes it down the chain. The handler business logic never needs to inspect the HTTP request headers directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-System Synergies &amp;amp; Friction Reduction
&lt;/h2&gt;

&lt;p&gt;By cross-referencing these subsystems, we can identify powerful synergies that eliminate developer friction and prevent systemic failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Friction Reduction: The Transactional Schema Guardrail
&lt;/h3&gt;

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

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

&lt;p&gt;To the junior developer, the code looks like standard single-tenant CRUD logic:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
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 reloading 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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>architecture</category>
      <category>go</category>
      <category>nuxt</category>
      <category>saas</category>
    </item>
    <item>
      <title>Building a Hypervisor for AuDHD: Containerising My Dual-OS Mind</title>
      <dc:creator>unexcitement</dc:creator>
      <pubDate>Mon, 28 Sep 2026 15:56:51 +0000</pubDate>
      <link>https://dev.to/unexcitement/building-a-hypervisor-for-audhd-containerising-my-dual-os-mind-4hin</link>
      <guid>https://dev.to/unexcitement/building-a-hypervisor-for-audhd-containerising-my-dual-os-mind-4hin</guid>
      <description>&lt;p&gt;If you have ever stared at your IDE completely paralyzed screaming internally to write a single line of code but physically unable to move society probably told you that you lack discipline. As a software engineer recently diagnosed with AuDHD (Autism + ADHD), I realized this isn't a failure of willpower. It is a catastrophic hardware and software conflict.&lt;/p&gt;

&lt;p&gt;I am currently organizing my research into a project titled "Debugging the human condition - Through the eyes of an AuDHD Software Engineer” by applying a systems theory lens to practically apply philosophy and psychology to learn to make the opposing forces work for you instead of pulling you a part leveraging my IT experience and specialisation in Software Engineering to use metaphors and systems diagrams comparing the metaphor to the real system.&lt;/p&gt;

&lt;p&gt;Through that systems theory lens, the default state of AuDHD makes perfect mechanical sense: it is exactly like dual-booting two entirely different operating systems without a bootloader to manage the switch, or a hypervisor to allocate resources. Because these systems have completely conflicting resource management protocols, they fight for the exact same constrained bare-metal hardware.&lt;/p&gt;

&lt;p&gt;However, as engineers, we do not simply accept failing architecture. We build the missing infrastructure. Here is how these two operating systems compete, and how I built a hypervisor to containerise the workloads.&lt;/p&gt;

&lt;p&gt;The Two Competing Operating Systems&lt;br&gt;
OS 1: The Autistic Monolith (State Management)&lt;br&gt;
The autistic side of the brain is a monolithic architecture optimized for deep processing and pattern recognition. It requires a rigidly controlled environment to function without throwing errors.&lt;br&gt;
Bottom-Up Compiling: A neurotypical brain relies on cached templates to quickly render a situation without heavy computation. The Autistic OS compiles everything from the source code, taking in every raw pixel of data and environmental variable to build the big picture.&lt;br&gt;
Dependency on cron Jobs: Because this is computationally expensive, the system relies on strict routines and predictable states the human equivalent of cron jobs. It needs to know exactly what is executing and when to manage its power draw.&lt;/p&gt;

&lt;p&gt;OS 2: The ADHD Event-Loop (Resource Allocation)&lt;br&gt;
The ADHD side is an event-driven architecture. Because its baseline fuel (dopamine) is chronically under-provisioned, the system constantly seeks out high-stimulation inputs.&lt;br&gt;
The Interest-Based Network: It prioritizes tasks by urgency, novelty, or genuine interest rather than logical importance.&lt;br&gt;
Asynchronous Polling: It relies on asynchronous polling, constantly spinning up new threads ("sidequesting") to chase stimulation.&lt;br&gt;
Aggressive Process Killing: It mercilessly kills long-running processes the exact moment the dopamine reward drops.&lt;/p&gt;

&lt;p&gt;The System Hang (An Out-Of-Memory Error)&lt;br&gt;
The climax of this systemic failure happens when OS 1 and OS 2 try to dictate the schedule simultaneously.&lt;/p&gt;

&lt;p&gt;Imagine building a perfectly structured weekly routine to keep the Autistic side regulated. By Wednesday, the ADHD side finds the lack of novelty physically repulsive and hijacks the main thread to research a brand new, unrelated project. The routine breaks, the Autistic side panics at the unhandled exceptions, and the system hangs.&lt;/p&gt;

&lt;p&gt;Your working memory acts as your system RAM. As the unhandled exceptions multiply, your mental RAM hits 100% utilization, and the biological Out-Of-Memory (OOM) Killer activates to save the hardware. The crushing exhaustion you feel is the cognitive equivalent of a CPU running at 100% just to resolve an internal conflict, leaving zero processing power for actual tasks.&lt;/p&gt;

&lt;p&gt;Deploying the Hypervisor: Containerisation and Load Balancing&lt;br&gt;
You cannot permanently run conflicting dependencies on bare-metal hardware without causing a server crash. To stop the system from thrashing, I had to build a cognitive hypervisor to isolate the environments.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cognitive Containerisation (Docker for the Mind)
When you attempt to write code, apply for jobs, and decompress all at the exact same desk using the same browser, your brain struggles to switch states because the environmental dependencies collide.
I deployed digital "bind mounts" to isolate these workloads.
This means using strictly separate browser profiles and user accounts for different goals (e.g., one profile strictly for job hunting, another entirely for business logic).
By enforcing these rigid containers, the Autistic OS receives a hardware-level signal that the context has safely shifted, completely eliminating cognitive dependency conflicts.&lt;/li&gt;
&lt;li&gt;The Strict Load Balancer (Serialised Execution)
The brain is a single-core processor; human multitasking is actually just rapid context switching (concurrency), which incurs a massive RAM overhead.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attempting to run the ADHD desire for novelty concurrently with the Autistic need for structure causes severe thread thrashing.&lt;br&gt;
To fix this, I implemented a strict architectural load balancer. I no longer allow the system to spin up a new workload until the active container is cleanly shut down and its state is saved.&lt;br&gt;
By executing tasks serially, the friction of deciding what to do next drops to zero.&lt;/p&gt;

&lt;p&gt;The Patch&lt;br&gt;
If your application crashes due to a memory leak, you do not call the server lazy. You profile the leak, isolate the failing subroutines, and write a patch.&lt;br&gt;
You are not lazy, you are not undisciplined, and you are not worthless. You possess an incredibly powerful, highly specialized dual-OS architecture. Once you stop judging yourself for missing standard societal metrics and start actively building the hypervisors, containers, and load balancers your hardware requires, it will change your life for the better.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
