Skip to main content
Blog

One Semantic Layer, Different Customer Schemas

Embedded AnalyticsReading time 12 min read
One Semantic Layer, Different Customer Schemas

One customer stores delivery times in minutes. Another uses hours. A third has an extra column for customs clearance that nobody else needs.

All three use your SaaS product. All three expect the same reporting interface to work.

At first, the differences are easy to accommodate. A custom query here, another dashboard there. But once you have dozens of customers with different data structures, every reporting update starts to feel like a migration project.

You change a shared metric, then discover that five customers have different implementations. You add a new dashboard and realize some customers don't have the required fields.

The problem isn't that your customers have different data. It's that your analytics architecture expects them not to.

A semantic layer helps establish common definitions, but multi-tenant SaaS needs an additional distinction: which parts of the analytical model must remain consistent, and which can vary between customers?

The shared schema is a contract, not a complete description of every customer

A multi-tenant reporting application needs a reliable foundation. If every customer receives a delivery performance dashboard, that dashboard should be able to rely on a consistent set of fields.

For example, the reporting model might require a delivery identifier, completion date, delivery status, and duration. Those fields support the standard calculations that every customer sees.

The problems begin when teams assume the shared schema needs to contain every field that any customer might eventually request.

One logistics company wants to analyze delays caused by customs inspections. Another needs to compare driver categories. A third tracks temperature violations for refrigerated shipments.

Adding all of these attributes to a universal reporting model may be technically possible. But it creates a growing collection of fields that many customers don't use, complicating documentation and maintenance.

The alternative isn't necessarily a separate dataset and dashboard for every customer. A more practical arrangement separates the shared analytical contract from customer-specific extensions.

Field Purpose Scope
delivery_id Identifies each delivery Shared
completed_at Reporting period Shared
delivery_duration Delivery performance Shared
delivery_status Completed, delayed, canceled Shared
customs_delay_minutes Customs-related delays Tenant A
driver_category Driver performance analysis Tenant B
temperature_violation Cold-chain compliance Tenant C

Illustrative schema showing shared reporting fields alongside tenant-specific extensions.

The first four fields form the contract for common reporting. The others extend the analytical possibilities for individual customers without changing what the standard dashboards require.

This distinction is also useful during development. When a customer requests a new field, the team can decide whether it belongs in the product's standard analytics or should remain an extension. Not every enterprise request needs to become a universal product feature.

What happens when the underlying schemas don't match?

There are different ways to organize multi-tenant data. Some SaaS applications use shared tables with tenant identifiers, while others maintain separate schemas, tables, or databases for individual customers.

The important distinction for reporting is whether the analytical interface can depend on a consistent structure.

Consider two customers whose delivery data lives in separate databases. Customer A has delivery_id, completed_at, delivery_duration, delivery_status and customs_delay_minutes. Customer B has the same first four fields plus driver_category.

Both have the fields required by the common delivery performance dashboard. They also have their own extensions.

Without an appropriate abstraction, a development team may need separate analytical configurations for each source. That becomes harder to maintain as additional customers arrive.

Luzmo's Custom Fields per Tenant (opens in new tab) addresses this scenario through a shared logical dataset and tenant-specific dataset sources. The base dataset establishes the common field structure. Individual tenants can use their own compatible tables or SQL queries, including additional columns that don't appear in the shared model.

There is a concrete compatibility requirement: shared fields in the tenant source must match the expected source_name, type, and source_type properties. The system validates this before saving and rejects incompatible schemas.

This matters because a shared dashboard cannot rely on a field that disappears or changes type when another tenant accesses it.

Luzmo also documents an important performance consideration: queries using tenant dataset sources don't use the base dataset's acceleration. They run against the tenant's own table or query.

As a result, testing a dashboard against the base dataset doesn't establish how it will perform against every customer source. Query complexity, indexing, database capacity, and customer data volumes can still produce different results. For teams already dealing with this, our embedded analytics performance guide explains the broader challenges of caching, concurrency, and query execution.

The dashboard works for Tenant A. Why doesn't it work for Tenant B?

This is where schema extensions become a product-design issue.

Suppose Customer A creates a chart showing average customs delays by month. The chart references customs_delay_minutes, which exists only in Customer A's source.

It's a legitimate reporting requirement, and there's no reason to force every other customer to store customs data. But moving that chart into the standard dashboard doesn't magically make the field available everywhere. Customer B has no corresponding column, and a query that relies on it can fail.

Luzmo's documentation explicitly distinguishes between shared fields and tenant-specific fields. Charts built around tenant-specific attributes aren't automatically portable to other tenants.

That creates a useful design principle:

Standard dashboards should depend on the shared schema. Customer-specific reporting can extend it, but those extensions shouldn't silently become dependencies of the standard experience.

There are several ways to reflect that boundary in the product. A company might give everyone a core reporting workspace, with additional customer-specific dashboards available where needed. Enterprise users could also create their own reports from fields assigned to their tenant.

The right interface depends on how much customization customers need. What's important is that the analytical architecture doesn't accidentally turn individual customer requirements into mandatory fields for everyone.

Field discovery helps, but it doesn't solve schema governance

Adding tenant-specific fields manually for every customer would undermine part of the benefit of a shared analytical model.

Luzmo can discover additional columns from the underlying tenant source when retrieving the dataset with its columns. These discovered fields subsequently become saved tenant-assigned fields when first used in a query, derived column, or formula.

That distinction between discovery and persistence is easy to overlook. A customer source may expose several extra columns; finding them doesn't mean they're already saved as persistent definitions in the logical dataset.

For a SaaS team building its own custom reporting interface, this affects how fields appear in selectors and how their state is managed.

However, automatic field discovery doesn't remove the need for data governance.

Consider a customer who changes customs_delay_minutes from a numeric field to text. The column may still exist, but the calculations built around it are no longer necessarily valid.

The reporting product needs a way to handle incompatible source changes, particularly when customers have created formulas based on those fields. A sensible implementation should establish which fields customers can use, which saved calculations depend on them, and how breaking changes are detected before they reach production.

Those processes are application-design responsibilities. They shouldn't be confused with features the analytics platform provides automatically.

Customer-specific formulas shouldn't change shared metrics

Additional fields are useful, but custom calculations are where customers can get more value from them.

A logistics company might want a delivery score that combines completion time with its contractual SLA. A retailer could define a margin measure using cost information specific to its business. The product team doesn't necessarily need to develop every calculation itself.

Luzmo supports tenant-assigned formulas and derived columns, with separate permissions for tenant-owned fields. Its embedding authorization model includes tenant_fields_rights, allowing applications to configure how authorized tenants work with their own analytical fields. Shared formulas remain protected from modification by tenant-scoped embed tokens.

This gives developers a way to provide analytical flexibility without exposing the common definitions to uncontrolled edits.

Capability Shared analytical model Tenant-specific extension
Standard KPI Maintained by SaaS team Available within permitted scope
Additional source column Not required for all tenants Accessible to its assigned tenant
Custom formula Shared formulas remain governed Authorized tenant can create or edit its own
Dashboard portability Based on common fields Depends on the tenant-specific fields used

Actual permissions depend on the configured authorization context and any applicable user or group rights.

Of course, letting customers write formulas doesn't mean every calculation will be correct. A formula editor still needs appropriate field descriptions, permissions, and validation.

But it changes the operating model. Instead of routing every reporting request through engineering, the product can offer controlled customization where it makes sense.

For the broader architecture, Luzmo's semantic layer connects governed analytical definitions with customer-facing dashboards and supported AI experiences.

Custom fields and tenant isolation solve different problems

It's tempting to group every tenant-related control under the heading of data security. That can hide an important difference.

Field visibility determines which analytical columns or formulas a tenant can access. Row-level security and other data-access controls determine which records the user can retrieve.

These aren't interchangeable.

A customer might be permitted to use a shared revenue field while being restricted to the revenue records belonging to its own organization. Hiding another tenant's custom column doesn't establish that the underlying rows are properly isolated.

Luzmo's Custom Fields documentation explicitly distinguishes field visibility from row-level security. Its broader embedding authorization capabilities address data access, including relevant filters and resource permissions.

The complete configuration also matters. tenant_fields_rights applies to the fields assigned to the token's own tenant, while the general rights setting applies to all other columns, so it doesn't automatically override everything inherited through users or groups.

Teams should therefore test both dimensions separately: whether customers can access only the intended fields, and whether queries return only authorized records. The distinction is covered further in our embedded analytics security guide.

What about AI analytics?

Customer-specific fields also raise an interesting question for AI-powered analytics.

If an enterprise customer creates a formula called Adjusted Delivery Score, should the AI assistant understand that metric when the user asks how deliveries performed?

The answer depends on how the analytical feature discovers available definitions, what context it receives, and which permissions apply.

Luzmo combines governed analytical definitions with knowledge and agent context to support AI-powered experiences. Its architecture also uses authorized analytical access rather than allowing unrestricted direct SQL execution by a language model.

However, the behavior of every tenant-created formula in every AI workflow shouldn't be assumed without testing.

For a realistic evaluation, create two tenants with different custom metrics. Ask questions in each tenant's context and verify that the returned information follows the correct definitions and access restrictions.

This is more useful than testing only whether the assistant can answer questions about a standard shared metric. It reflects what happens when customers begin personalizing analytics within a real SaaS product.

A better way to test the architecture before rollout

A proof of concept with identical tenant datasets won't reveal the problems this architecture is supposed to handle. A stronger test uses genuinely different schemas.

Create a shared delivery reporting model with a small set of required fields. Then connect two customer sources, each with its own extra columns.

The standard dashboard should work across both customers using the common fields. Tenant A should be able to use its own extension without gaining access to Tenant B's fields.

Now deliberately introduce a schema problem. Remove one required shared field or change its data type. Verify that the configuration identifies the incompatibility rather than allowing a report to return misleading results.

Next, create a customer-specific formula and test what happens when its source field changes. Check permissions separately from field availability, and measure query performance against the actual tenant sources.

These scenarios reveal the operational boundaries of the design much more clearly than a demonstration with two identical datasets.

For broader deployment requirements, our multi-tenant analytics guide covers source isolation and embedding patterns that complement this approach.

One semantic foundation doesn't require identical customer data

The promise of a semantic layer is often expressed as defining metrics once and reusing them across analytical experiences. In multi-tenant SaaS, that promise needs qualification.

Your customers may share the same reporting interface without having identical schemas or business requirements.

The goal isn't to eliminate those differences. It's to prevent them from forcing your team to maintain a separate version of the entire reporting system for every customer.

Luzmo's approach combines a shared logical dataset with compatible tenant-specific sources, additional fields, and authorized custom formulas. It creates a distinction between the reporting contract your product maintains and the extensions individual customers need.

That distinction comes with rules. Shared fields must remain compatible, tenant-specific charts aren't universally portable, and field visibility doesn't replace data-access security.

But those boundaries are useful. They let engineering teams maintain a consistent core while supporting customers whose analytical requirements go beyond the standard dashboard.

Explore Luzmo's semantic layer and the Custom Fields per Tenant documentation (opens in new tab) to see how the architecture works.

FAQ

All your questions answered.

  • Do all tenants need identical schemas for a shared dashboard?

    No. They need to share the fields the dashboard depends on. A shared analytical contract defines the required fields — identifier, date, status, duration — and each tenant's source must expose those with matching source_name, type and source_type. Beyond that contract, tenants can carry extra columns the shared dashboards never reference.

  • Why does a chart that works for one tenant fail for another?

    Because it references a field that only exists in the first tenant's source. Charts built on tenant-specific attributes are not portable to other tenants. Standard dashboards should depend only on the shared contract; customer-specific reporting can extend it, but those extensions should not quietly become dependencies of the standard experience.

  • Is field visibility the same as row-level security?

    No, and conflating them is a common mistake. Field visibility decides which analytical columns or formulas a tenant can use. Row-level security decides which records a query returns. A customer can be allowed to use a shared revenue field while being restricted to its own revenue rows. Hiding another tenant's column proves nothing about whether the underlying rows are isolated.

  • Does automatic field discovery remove the need for schema governance?

    No. Discovery finds extra columns in a tenant source; it does not make them governed definitions. If a customer changes a numeric field to text, the column still exists but the calculations built on it may no longer be valid. The application still needs to decide which fields customers can use, which saved calculations depend on them, and how breaking changes get caught before production.

  • Can customers create their own formulas without affecting shared metrics?

    Yes, with the right permissions model. Luzmo supports tenant-assigned formulas and derived columns, and its embedding authorization includes tenant_fields_rights so an application can control how an authorized tenant works with its own fields. Shared formulas stay protected from tenant-scoped embed tokens.

  • Will a POC with identical tenant datasets tell me anything useful?

    Not about this problem. A test with two identical datasets cannot reveal the failures this architecture exists to handle. Use genuinely different schemas, then deliberately break one — remove a required shared field or change its type — and check that the configuration catches the incompatibility rather than returning misleading results.

Written by

Kinga Edwards
12 min read

Ship the future of your data

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

Sean Patterson — Luzmo account executive

Book your session with our analytics expert.