The central challenge of agency client reporting is this: you want one shared environment — one set of reports to maintain, one BI instance to operate — but each client must see only their own data. Client A cannot see Client B's records, even if they're running the same report against the same underlying database. This is the data isolation problem, and it's the reason row-level security is not optional in a multi-tenant reporting setup.
This chapter covers how data isolation actually works in a shared BI environment, how DashboardFox's Data Tags implement it, and what the practical boundaries are.
The Problem with Application-Layer Filtering
The naive solution to data isolation is to build separate filtered dashboards per client — hardcode a WHERE client_id = 'acme' clause into every report for the ACME client, and equivalent filters for every other client. This works for two clients. It becomes a maintenance problem at ten and an operational failure at twenty-five.
Every time a report changes, you update it N times. Every time you add a new report, you build N copies. And any human error — a wrong filter value, a missing WHERE clause — leaks one client's data to another. That's a breach, not a configuration mistake.
The correct solution pushes filtering into the security layer, not the report layer. The report is built once. Security policy attached to the user determines what data they're allowed to see. The filter is applied automatically at query execution time, before results are returned.
Row-level security enforces data isolation at the query level. When a client user runs a report, the BI system automatically appends a filter based on that user's security policy — restricting results to only the rows they're authorized to see. The report query is identical for every user; the results differ based on who's asking. See the Row-Level Security Guide for a complete technical explanation.
How Data Tags Work in DashboardFox
DashboardFox implements row-level security through a feature called Data Tags. The model is straightforward: you define a tag (typically matching a value in your data, like a client ID, account name, or region), assign that tag to a user or user group, and then configure your reports to filter on that tag value. When a tagged user runs the report, the system automatically applies the matching filter.
The key property of Data Tags is that they're assigned at the user level and propagate automatically to every report configured to use them. You don't build per-client report variants. You build one report, configure it to filter on the client tag, and the security layer handles the rest for every user in the system. Add a new client — create their user accounts, assign their data tag, and they immediately see filtered results across all reports that use that tag.
This "assign once, filters everywhere" model is the right architecture for agency-scale client reporting. For a deeper technical walkthrough of how Data Tags work, see Chapter 4 of the Row-Level Security Guide.
What Data Tags Can and Cannot Do
Data Tags handle the row-filtering requirement — restricting which records a user sees in a given dataset. They are not the full picture of a multi-tenant security implementation.
Report-level access control is a separate layer. A user might have a data tag that restricts their row access, but you also need to control which reports and dashboards they can see in the library. If Client A and Client B are both in the same DashboardFox instance, they should only see reports relevant to their engagement — not each other's. This is managed through DashboardFox's permission system: reports and folders are granted to specific user groups, so each client's users only see what they're supposed to.
The combination — report-level permissions controlling what's visible in the library, plus Data Tags controlling what data is returned when a report runs — gives you complete multi-tenant isolation without separate instances.
The Guest/Anonymous Access Consideration
DashboardFox supports anonymous (guest) report access — a report or dashboard accessible via a public link without requiring login. This is useful for publicly shared content, but it's important to understand how it interacts with multi-tenant security.
Guest branding and the guest library are server-level configurations — one setting applies to all anonymous users across the entire workspace. There's no per-client branding for guest access, because guest users haven't authenticated and therefore have no user-level policy applied to them. If you share a report link publicly, all visitors see the same guest experience.
The practical implication: for client-specific data that needs to stay isolated, require login. Use authenticated access with Data Tags for anything that needs per-client filtering. Guest/public access is appropriate for genuinely public content where data isolation isn't a requirement — and where you're comfortable with the same branding applying to all anonymous viewers.
You can, however, use custom domains when sharing authenticated report links — which does allow branded URLs for specific clients even in a shared environment. The branding on those links reflects the domain's configured policy, while the data isolation is still handled by the logged-in user's data tags.
Single-Tenant vs. Multi-Tenant: When Each Makes Sense
Multi-tenant is almost always the right model for agencies managing multiple clients on their own infrastructure. One environment to maintain, one billing relationship, one place to update reports when data structures change. Data Tags handle isolation; branding policies handle per-client presentation.
Separate instances (single-tenant per client) make sense in specific situations: when a client's contract requires physical data segregation, when a client has data residency requirements that dictate their data can't co-reside with others, or when a client is large enough that their BI usage warrants a dedicated environment for performance reasons.
DashboardFox's self-hosted option ($6,995 one-time) is relevant here — some agencies run a dedicated self-hosted instance for a large enterprise client, while serving smaller clients out of a shared cloud environment. Both models can run simultaneously.
Practical Checklist: What to Verify Before Going Live
Before you open a multi-tenant portal to client users, verify these things are in place:
Every client user account has a data tag assigned that corresponds to their records in the underlying data. Every report that contains client-identifiable data is configured to filter on that tag. The client's user group only has access to reports and folders intended for that client. You've tested by logging in as a client user and confirming they see only their data — and cannot navigate to reports belonging to other clients. Scheduled email delivery has been verified to send to the correct recipients.
These aren't one-time setup tasks — they're part of the onboarding checklist for every new client added to the environment. For more on DashboardFox's security architecture, see the Security page.
DashboardFox includes Data Tags (row-level security) and multi-tenant support on every plan, starting at $99/mo. No enterprise tier required.
How do you keep client data separate in a shared BI environment?
Row-level security enforces per-client data isolation at the query level. Each client user is associated with a data tag that automatically filters every report they run to return only their rows. The filter is applied by the BI system before results are returned, so clients cannot access data outside their permitted scope even if they try.
Do I need separate BI instances for each client?
Not if your BI tool supports row-level security. A single shared instance can serve many clients with complete data isolation, provided each client's users have data tags applied that restrict their query results to their own records. Separate instances are only necessary when clients require physical data segregation for compliance, contract, or data residency reasons.
Can anonymous / guest users get per-client data isolation?
No. Guest/anonymous access is unauthenticated — because there's no login, there's no user identity to apply row-level security against. Anonymous access is appropriate for publicly shared content where data isolation isn't required. Client-specific data that needs isolation must require login so that security policies can be applied based on the authenticated user's identity.
