Skip to main content
Blog

How to Implement Multi-Tenant Analytics

Embedded AnalyticsReading time 12 min read
How to Implement Multi-Tenant Analytics

A dashboard can look perfect and still be fundamentally unsafe if the wrong customer can see it.

Implementing multi-tenant analytics starts with four decisions: choose how tenant data will be isolated, enforce that isolation at the data layer, carry tenant context through authentication and build dashboards that can safely serve many customers without being recreated for each one.

TL;DR: decide the isolation model first. Then make tenant identity part of every data request, keep access rules out of the frontend and design the analytics layer so one governed dashboard can serve many customers.

If you need the broader concept first, start with what multi-tenancy means for embedded analytics. This guide is about implementation.

Why tenant isolation comes before the dashboard

In an internal dashboard, a bad filter can produce the wrong number.

In customer-facing analytics, a bad tenant filter can expose another customer's data.

That's a different class of problem.

Once analytics sits inside a multi-customer SaaS product, every route to data has to respect the same customer boundary. That includes dashboards, drill-downs, exports, API requests and any background jobs that generate reports.

You can't rely on the interface to enforce that boundary.

Hiding a customer selector doesn't isolate data. Passing a tenant ID from the browser and trusting it without server-side validation doesn't isolate data either.

The application needs a reliable answer to one question before every analytics request:

Which tenant is this user allowed to act as?

Once you have that answer, the rest of the architecture becomes much easier to reason about.

Step 1: Choose your tenant-isolation model

There isn't one correct multi-tenant architecture.

The right model depends on how your application already stores customer data, how strongly customers need to be isolated and how much operational complexity your team wants to own.

Three patterns come up most often.

Shared schema with a tenant ID

All customers share the same tables and each tenant-owned row carries an identifier such as tenant_id.

A simplified table could look like this:

orders

id tenant_id revenue status 101 tenant_a 1200 shipped 102 tenant_b 870 pending 103 tenant_a 540 pending

This model is efficient because you don't need a separate database or dataset for every customer.

It also makes one rule non-negotiable: every query that can touch tenant data needs to respect the tenant boundary.

For many SaaS applications, this is where row-level security or equivalent centralized filtering becomes important.

Separate database or data source per tenant

At the other end of the spectrum, each customer has its own database, schema or other isolated data source.

That gives you a strong structural boundary. Customer A's rows aren't mixed with Customer B's rows because they aren't stored together.

The tradeoff is operational.

Ten customers may be easy to handle this way. Ten thousand customers mean thousands of connections, migrations, monitoring paths and lifecycle events unless that infrastructure is heavily automated.

Hybrid isolation

Some products use both.

Most customers may live in a shared multi-tenant environment, while larger or regulated accounts receive dedicated infrastructure.

You might also separate some high-risk datasets while keeping less sensitive product data pooled.

The result can offer more flexibility, but it creates another requirement: the analytics layer needs to know which access path applies to the tenant currently logged in.

Model Isolation Operational complexity Typical fit
Shared schema + tenant ID Logical Lower SaaS products with many customers and consistent data models
Separate source per tenant Structural Higher Customers needing stronger physical separation or custom data environments
Hybrid Mixed Medium to high SaaS products serving both standard and enterprise tenants

Don't pick the model because it looks cleanest in an architecture diagram.

Pick the one your team can enforce consistently when new tenants, new reports and new analytics features are added.

Step 2: Enforce tenant access at the data layer

Suppose your shared table includes tenant_id.

This isn't enough:

SELECT * FROM orders;

And this is only safe if your application can guarantee where tenant_id comes from:

SELECT * FROM orders WHERE tenant_id = $1;

The dangerous version is letting $1 come directly from a value the user can manipulate.

Tenant context should come from authenticated server-side state.

In systems that support native row-level security, you can centralize that rule closer to the data.

A simplified PostgreSQL-style example looks like this:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON orders USING ( tenant_id = current_setting('app.tenant_id') );

The application establishes the tenant context after authentication. The database policy then limits which rows the request can see.

That's useful because developers don't have to remember to add the same tenant condition to every new query.

The implementation doesn't have to be PostgreSQL RLS specifically. Your stack may enforce isolation through parameterized queries, a semantic layer or another centralized authorization mechanism.

The principle matters more than the syntax:

Don't make tenant isolation depend on every developer remembering the rule every time.

Luzmo supports the same idea at the analytics layer. For shared multi-tenant datasets, Embed Authorization can carry parameter overrides used for dynamic tenant filtering. For setups with a different data source per tenant, connection overrides can point the embed toward the correct source.

See how Luzmo handles tenant-aware embedded analytics.

Step 3: Carry tenant context from login to every analytics request

Tenant isolation breaks when different parts of the application disagree about who the current tenant is.

Imagine a user signs in to Account A.

Your app correctly identifies:

user_id: 1842 tenant_id: account_a role: manager

The dashboard request needs to inherit that context.

So does an export.

So does an API call triggered from the dashboard.

So does a scheduled report created from that session.

The browser shouldn't be responsible for inventing or validating the tenant.

Instead, your server should derive tenant context from the authenticated user and use it when creating analytics authorization.

With Luzmo, Embed Authorization tokens are created server-side using the organization's API credentials. The resulting short-lived embed credentials can then be passed to the frontend without exposing the underlying API key and token.

A simplified Node example could look like this:

const embed = await client.create('authorization', { type: 'embed', username: user.id, name: user.name, email: user.email, suborganization: account.id,

access: { // Dashboards and datasets this user can access },

parameter_overrides: { tenantId: account.id } });

Then the client gets only the temporary embed credentials:

<luzmo-embed-dashboard authKey={embed.id} authToken={embed.token} />

In Luzmo, suborganization can group users belonging to the same customer, while parameter_overrides can feed tenant-specific values into parameterized filtering. The exact authorization object depends on your resource setup, but the architectural pattern stays the same.

Authentication answers who is this user?

Tenant context answers which customer's world are they operating inside?

Your analytics layer needs both.

Step 4: Build dashboards once, then apply tenant context

A common early implementation looks like this:

Customer A → Dashboard A Customer B → Dashboard B Customer C → Dashboard C

It works.

Then you get Customer D.

And Customer E.

Then someone asks for a new metric and you realize the same dashboard now exists 47 times.

That's not multi-tenant analytics. That's dashboard duplication.

Where customers share the same analytics use case, build the dashboard structure once and let tenant context determine which data appears.

The better model is:

Reusable dashboard ─┼─ Tenant B data ├─ Tenant C data └─ Tenant D data

The chart definitions, layout and product behavior stay reusable.

The data changes at runtime.

This doesn't mean every customer has to receive an identical experience. Enterprise tenants might have additional datasets, features or custom views.

But variation should be intentional.

Don't create a new dashboard simply because the data belongs to another customer.

Reusable analytics matters for more than maintenance. It also makes releases safer.

When you fix a calculation, update a visualization or improve a workflow, you can roll that improvement through the shared experience instead of discovering months later that twelve customer-specific copies are still using the old version.

Step 5: Separate tenant isolation from tenant customization

Once isolation works, another question appears:

How different should analytics be for each customer?

This is where teams sometimes mix two separate problems.

Isolation decides what a customer is allowed to access.

Customization decides how their analytics experience should look or behave.

Keep those concerns separate.

A customer might have its own:

  • branding
  • available dashboards
  • user roles
  • feature permissions
  • default filters
  • editable analytics capabilities

None of those should weaken the underlying tenant boundary.

For example, giving an account administrator more dashboard controls shouldn't give them access to another customer's dataset.

Similarly, changing a customer's logo or color scheme shouldn't require duplicating their entire analytics deployment.

Luzmo's Embed Authorization model can scope access to specific datasets and dashboards, while its embedded setup also supports tenant-aware feature access and theming.

For the UX side of that setup, see white-label embedded analytics.

And if you're planning the complete customer rollout rather than just the tenant architecture, the companion guide on how to add customer-facing analytics to a SaaS product covers permissions, native UX, launch and packaging from the product side.

This separation between the analytics infrastructure and the product experience is also what gives teams room to customize without rebuilding the foundation. Sarah Nerby, Senior Software Engineer at Element Logic, puts it this way: “Luzmo Flex has empowered us to go beyond the constraints of traditional dashboards, allowing us to easily create custom data analytics with unprecedented flexibility.”

Where multi-tenant analytics implementations usually fail

Most failures aren't caused by teams having no tenant architecture at all.

They're caused by one path forgetting it.

A new query skips the tenant condition

The main dashboard is correctly filtered, but a developer adds a new drill-down endpoint without applying the same restriction.

That's exactly why centralized enforcement is safer than relying on conventions.

An asynchronous job loses tenant context

A user triggers an export while working inside Tenant A.

The export runs ten seconds later in a background worker.

If the job only saved the report ID and not the authorized tenant context, the worker may no longer know which customer boundary to apply.

Tenant identity needs to survive beyond the original HTTP request when the workflow does.

Cache keys don't include tenant identity

Suppose two tenants request the same dashboard.

If the cache only uses:

dashboard_id

instead of something tenant-aware such as:

tenant_id + dashboard_id

you've created a potential path for one customer's result to be reused for another.

The UI is treated as the security boundary

A hidden dropdown isn't access control.

Neither is a disabled button.

If a user can alter a request outside the interface and retrieve another tenant's data, the architecture isn't isolated.

New tenants are provisioned manually

Manual setup works until someone forgets a step.

As the product scales, onboarding should establish the required tenant identifiers, groups, connections and default access rules consistently.

Admin roles quietly become global roles

“Admin” means different things in different systems.

A customer admin usually means “admin inside this customer's account.”

It shouldn't automatically mean “can access every customer in the SaaS platform.”

That distinction needs to stay explicit in your authorization model.

Multi-tenant analytics implementation checklist

Before shipping, you should be able to answer yes to each of these.

  • Isolation model chosen: we know whether tenant data is pooled, siloed or hybrid.
  • Tenant identity is authoritative: it comes from authenticated server-side context, not a user-editable browser value.
  • Access is centrally enforced: queries can't retrieve another tenant's data just because a developer forgot a UI filter.
  • Background paths preserve context: exports, jobs and other asynchronous operations still know which tenant initiated them.
  • Dashboards are reusable: we aren't duplicating the same analytics experience for every customer without a real reason.
  • Customization doesn't bypass isolation: branding, roles and self-service features sit on top of the tenant boundary.
  • Failure cases are tested: we deliberately try the wrong tenant ID, wrong role and missing access before launch.

If one of these answers is “mostly,” that part probably isn't ready yet.

Build the tenant boundary once

Multi-tenant analytics becomes hard when tenant logic is scattered everywhere.

If each query, dashboard and workflow has to remember how isolation works, every new analytics feature introduces another opportunity to get it wrong.

A better implementation gives the system one reliable source of tenant context, enforces access centrally and lets reusable dashboards sit on top of that boundary.

Then adding Customer 500 shouldn't require building Analytics System 500.

Talk to the Luzmo team about your architecture.

FAQ

All your questions answered.

  • What's multi-tenant analytics?

    Multi-tenant analytics lets one analytics system serve multiple customers while keeping each customer's data and access separate. The same application and often the same dashboard definitions can serve many tenants, while authentication and data-access rules determine what each user can see.

  • Should every tenant have a separate database?

    No. Many SaaS products use shared tables with a tenant identifier and enforce isolation through row-level security or equivalent filtering. Separate databases can provide stronger structural isolation but create more operational overhead. Hybrid models are also common.

  • What's row-level security in multi-tenant analytics?

    Row-level security restricts which rows a user or request can retrieve based on rules such as tenant identity. Instead of relying only on application code to add a tenant filter, the access rule is enforced closer to the data.

  • Is adding `WHERE tenant_id = ...` enough?

    It can be part of a safe design, but only if the tenant value comes from trusted server-side context and every relevant query consistently applies the rule. Centralized enforcement reduces the risk of one forgotten condition exposing another tenant's data.

  • Can one dashboard serve multiple customers?

    Yes. In many multi-tenant systems, the dashboard structure is reused and tenant context changes the underlying data at runtime. That's usually easier to maintain than creating a separate dashboard copy for every customer.

  • How do you pass tenant context to embedded analytics?

    Derive the tenant from the authenticated application user, then include that context when creating the analytics authorization server-side. With Luzmo, Embed Authorization can use properties such as `suborganization`, resource access and parameter overrides to scope the embedded experience.

  • What if every customer has a separate database?

    The analytics layer needs to route each authenticated tenant to the correct connection. Luzmo supports connection overrides for setups where different tenants use different underlying data sources.

  • How should we test tenant isolation?

    Don't only test the expected customer path. Try changing tenant identifiers, opening resources a user shouldn't have, using roles with less access, triggering exports and testing background workflows. The goal is to prove that the tenant boundary survives even when the request isn't behaving as expected. *Last updated: September 2026*

Written by

Kinga Edwards
12 min read

Ship the future of your data

Let us show you what Luzmo can do for your product.

Thijs van Gulik — Luzmo account executive

Book your session with our analytics expert.