Et'al Software Solutions
Back to blog
EngineeringJanuary 10, 2026·8 min read

How We Built Multi-Tenant Architecture

A deep dive into our approach to multi-tenancy, including row-level security and workspace isolation.

Sarah Chen

CTO

The Multi-Tenant Challenge

Building multi-tenant applications presents unique challenges. How do you ensure one customer can never access another's data? How do you handle account switching without data leakage? How do you scale efficiently while maintaining strict isolation?

These questions drove our architecture decisions. We needed a solution that was secure by default, performant at scale, and simple to work with.

The Feed Field Pattern

At the heart of our multi-tenant architecture is the "feed" pattern. Every tenant-scoped table includes a `feed` column that references the account's unique identifier.

This pattern, combined with Supabase's row-level security, means tenant isolation is enforced at the database level—not in application code. Even if a developer forgets to add a WHERE clause, the database prevents cross-tenant data access.

The feed field approach also simplifies querying. Use the `!inner()` join pattern to automatically filter by the current tenant context.

Row-Level Security Policies

Our RLS policies follow a consistent pattern across all tenant-scoped tables:

**SELECT policies** verify the user belongs to an account with access to the feed.

**INSERT policies** ensure the feed field matches the user's current account context.

**UPDATE and DELETE policies** combine ownership verification with feed-based isolation.

We also implement a 14-role permission hierarchy, from basic viewers to system administrators, all enforced at the database level.

Performance Considerations

Multi-tenancy doesn't have to mean slow queries. We optimize performance through:

- **Proper indexing** on feed fields and commonly queried columns - **Query key factories** that include account IDs, enabling aggressive caching - **Prefetching patterns** that load workspace data during navigation - **Optimistic updates** that provide instant feedback while mutations complete

Our patterns achieve sub-100ms response times even with millions of records across thousands of tenants.

Account Switching

Users often belong to multiple organizations. Our account switching implementation handles this gracefully:

1. The workspace context tracks the current account 2. Query keys include the account ID, so switching invalidates only relevant caches 3. A loading provider prevents flash of wrong data during transitions 4. Server-side validation ensures the user has access to the selected account

This creates a seamless experience when moving between workspaces.