A Developer's Guide to Data Isolation and Row-Level Security
As the founder of an embedded analytics platform, I've spent countless hours navigating the complexities of data architecture. In the early days of building SaaS products, long before Dashrendr, I learned a hard lesson about multi-tenancy the hard way: a single logical flaw in your data access layer can expose one customer's data to another. It's the kind of mistake you only make once. This guide is the resource I wish I had back then—a straightforward, platform-agnostic look at building secure multi-tenant dashboards.
Disclosure: This article is published by Dashrendr. Where Dashrendr is relevant, I say so directly—including its limitations.
What is Multi-Tenancy in a SaaS Context?
First, let's establish a clear definition. Multi-tenancy is an architectural principle where a single instance of a software application serves multiple customers. Each customer is called a "tenant." Tenants share the application and, typically, the underlying infrastructure and databases, but their data is logically isolated and remains invisible to other tenants. Think of it like an apartment building: everyone shares the main structure, plumbing, and electricity, but each resident has their own private, locked apartment.
This approach is the backbone of the SaaS industry. Platforms like Salesforce, Shopify, and even our own Dashrendr are multi-tenant. The alternative, a single-tenant architecture (one software instance per customer), is far more expensive and complex to manage. According to a report by the SaaS Business Review, multi-tenancy can reduce infrastructure and operational costs by up to 40% compared to single-tenant models, making it the default choice for most SaaS startups.
The key challenge, and the focus of this guide, is ensuring that the walls between those apartments are impenetrable. This is where data isolation comes in—the practice of keeping one tenant's data completely separate and inaccessible from another's.
Architectural Patterns for Multi-Tenant Data Isolation
When you're building a multi-tenant application, you have three primary architectural patterns to choose from for handling data. Each has significant implications for security, performance, cost, and complexity, especially when it comes to your customer-facing analytics.
- Separate Databases per Tenant: This is the most isolated approach. Each tenant gets their own dedicated database. It offers the strongest possible guarantee of data separation. However, it's also the most expensive and operationally complex. Managing migrations, backups, and connections for hundreds or thousands of individual databases can quickly become a nightmare for a small team.
- Shared Database, Separate Schemas: A popular middle ground. All tenants reside within a single database instance (e.g., a single PostgreSQL server), but each tenant has their own schema. This provides strong logical isolation and is easier to manage than separate databases. It's a solid choice for applications with a moderate number of tenants where data complexity varies.
- Shared Database, Shared Schema: This is the most common pattern for modern SaaS applications due to its cost-effectiveness and scalability. All tenants' data resides in the same set of tables, and a mandatory `tenant_id` (or `customer_id`, `org_id`, etc.) column on every relevant table distinguishes which data belongs to whom.
The architectural takeaway is this: A shared database, shared schema model places the entire burden of data isolation on your application's logic. Every single database query must include a `WHERE tenant_id = ?` clause. Forgetting it just once in your code can lead to a catastrophic data leak.
Implementing Row-Level Security (RLS)
For teams using the shared-schema model, relying solely on application-level code to filter by `tenant_id` can be risky. This is where a powerful database feature comes into play: Row-Level Security (RLS). RLS is a feature in modern databases like PostgreSQL and SQL Server that allows you to define security policies directly on a table. These policies automatically and transparently add `WHERE` clauses to queries, filtering data based on the current user's session attributes.
For example, you could create a policy on your `invoices` table that says, "A user can only see rows where the `invoices.tenant_id` matches the `current_setting('app.tenant_id')`." Once enabled, you set this `app.tenant_id` variable when a user authenticates. From that point on, even if a developer writes a query like `SELECT * FROM invoices;`, the database itself will enforce the policy and only return the invoices for that specific tenant. It acts as a critical safety net, making data leaks nearly impossible at the database layer. For a deep dive on this, the PostgreSQL documentation on RLS is an excellent authoritative resource.
Multi-Tenancy in Embedded Analytics
The need for strict data isolation becomes even more critical when implementing a multi-tenant dashboard for your customers. Your embedded analytics solution *must* be able to integrate with and respect your chosen tenancy model. As the SERP analysis shows, vendors like Metabase and AWS QuickSight have built-in features for this, but they often lock you into their specific way of managing tenants.
At Dashrendr, we took a different, more flexible approach. We believe your application should be the single source of truth for tenancy. Dashrendr integrates with your existing architecture in two primary ways:
- Direct Database Connection: If you use a database like PostgreSQL or MySQL with Row-Level Security enabled, you can provide Dashrendr with a read-only user. When your application requests a dashboard for a specific tenant, it authenticates with the database and sets the session `tenant_id`. All subsequent queries from Dashrendr for that dashboard automatically inherit the RLS policies. The data filtering happens at the database level before it ever reaches our platform, which is the most secure posture. This push-down aggregation is currently supported for PostgreSQL, MySQL, and BigQuery.
- REST API Push Ingestion: If you prefer to keep your database private or use a different tenancy model, you can push data to Dashrendr's REST API. In this model, your backend is fully responsible for fetching the correct data for a given tenant and pushing it to a corresponding dataset in Dashrendr. This gives you complete control but also puts the full responsibility for data isolation on your code. It's a great option for those who want to connect a database securely via an API.
A limitation to be aware of in Dashrendr is that we do not yet support cross-connection joins. This means you can't join data from a PostgreSQL database with a Google Sheets source within a single chart. All data for a dashboard should be prepared and available from a single source or pushed via the API.
What is an example of a multi-tenant software?
Many of the tools you use every day are multi-tenant. A classic example is Salesforce. Thousands of companies log into the same Salesforce platform, but the application architecture and database design ensure that one company cannot see another company's leads, contacts, or opportunities. Other great examples include Shopify, where thousands of merchants run their stores on a shared platform, and Google Workspace, where your company's documents are stored on the same infrastructure as millions of others, but are kept completely private.
What is a multi-tenant cluster?
The term "multi-tenant cluster" typically refers to infrastructure, most commonly a Kubernetes cluster, that is configured to run workloads from multiple different tenants. In this context, tenants could be different teams within a large organization or different customers of a SaaS platform. According to the official Kubernetes documentation, isolation is achieved using features like Namespaces to create virtual clusters, ResourceQuotas to limit CPU and memory usage, and NetworkPolicies to control traffic flow between pods. This ensures that even if tenants are sharing the same physical nodes, their applications run in isolated, secure environments.
Conclusion: The Right Architecture for Your SaaS
Choosing the right multi-tenant architecture is a foundational decision for any SaaS developer. While separate databases offer maximum isolation, the shared schema model combined with Row-Level Security provides a powerful, scalable, and secure framework for the vast majority of applications.
When it comes to adding customer-facing analytics, don't let your embedded BI tool dictate your architecture. Choose a flexible solution that adapts to *your* security model. Whether you enforce tenancy at the database level with RLS or within your application logic, your analytics platform should be a seamless, secure extension of that choice.
If you're grappling with these challenges, we invite you to explore Dashrendr. Our platform is designed by developers, for developers, with a focus on security and flexibility. Plans start at just $6/month, and you can see how it works with your own data with a 14-day free trial, no credit card required.
Tags
What is Cohort Analysis? A Guide for SaaS Teams
A comprehensive guide for SaaS founders and developers on cohort analysis. We break down what cohorts are, why they are essential for tracking SaaS metrics like retention and churn, and provide a step-by-step guide on how to conduct a cohort analysis for your own product.
What Is Data Aggregation? A Dev's Guide for SaaS
A developer-focused guide to data aggregation for SaaS dashboards. This post breaks down what data aggregation means, why it's critical for performance and cost, how it compares to ETL, and practical ways to implement it using direct database connections or a REST API.
What Is a Stacked Area Chart? A Guide for SaaS Teams
A comprehensive guide to stacked area charts for SaaS developers. This post covers what they are, when to use them, how to read them, and key differences from other charts like line charts. Learn how to visualize part-to-whole relationships over time effectively in your analytics dashboards.
