Skip to main content

Dynamic data sources for embedded analytics

Introduction

When implementing embedded analytics, you often need to serve customers who each have their own separate databases. Rather than creating duplicate dashboards for every customer, you can configure a single embedded dashboard that dynamically connects to the appropriate database based on which customer is viewing it.

This guide walks you through setting up Dynamic Data Sources for embedded analytics. You'll learn how to pass a data source identifier in your embed payload and have Holistics automatically route queries to the correct database.

How it works

Before diving into implementation, here's how the dynamic data source mechanism works at a high level:

Dynamic data sources for embedded

The flow works like this:

  1. Your backend identifies the customer - When a user accesses your embedded dashboard, your application determines which database they should connect to
  2. You pass the data source in the embed payload - Your backend includes a data_source user attribute in the signed embed token
  3. Holistics routes the query - When the dashboard loads, Holistics reads the data_source attribute and directs all queries to the specified database connection

This approach lets you maintain a single dashboard definition while serving data from multiple customer databases.

tip

For a deeper understanding of the underlying mechanism, see Dynamic Data Source in the Development documentation.

Dynamic data source implementation

Follow these five steps to configure dynamic database connections for your embedded dashboards.

Step 1: Connect your client databases

First, connect all of your customers' databases to Holistics.

When naming each data source, use a unique and meaningful identifier (e.g., customer_acme, customer_globex). You'll reference these names in your embed payload to specify which database to use.

Step 2: Create the data_source user attribute

Before you can pass the data_source value in your embed payload, you need to define it as a user attribute in Holistics.

Navigate to Settings > User Attributes and create a new attribute named data_source. See User Attributes Documentation for detailed instructions.

data_source user attribute

Step 3: Create a dynamic variable in AML

Next, create an AML variable that reads the user attribute and provides a fallback value.

Go to the Development tab, create a new file (e.g., embedded_variables.aml), and add:

const client_data_source = if (H.current_user.data_source) {
H.current_user.data_source
} else {
'default_data_source'
}

The fallback value ('default_data_source') is used when no data_source attribute is provided - useful for testing or default behavior.

tip

You can name the file and variable anything you like, as long as the file ends with .aml and the variable name is valid AML syntax.

Step 4: Update your dataset configuration

Modify the dataset that powers your embedded dashboard to use the dynamic variable:

Dataset dynamic_client_dataset {
label: 'Dynamic Client Dataset'
data_source_name: client_data_source
models: [orders]
relationships: []
}

Now the dataset will connect to whichever data source is specified in the embed payload.

Step 5: Pass data source in your embed payload

Finally, when generating the embed token on your backend, include the appropriate data source name based on the logged-in customer:

// Embedded payload
embedded_payload = {
permissions: {},
user_attributes: {
data_source: ['customer_acme'] // Replace with the customer's data source name
}
}

Your backend logic should determine the correct data source name based on your customer identification system.

Testing in embed sandbox

Before deploying to production, use the Embed Sandbox to verify your dynamic data source configuration works correctly. You can test different data_source values and confirm that queries route to the expected databases.

dynamic schema sandbox

Alternative: Dynamic schema

If your customers share the same database but use different schemas (common in multi-tenant architectures), you can use schema instead of data_source. The setup follows the same pattern—the key difference is where you apply the variable.

Instead of setting data_source_name at the dataset level, you interpolate the schema into table_name or query at the model level:

// Define the variable (same pattern as data_source)
const client_schema = if (H.current_user.schema) {
H.current_user.schema
} else {
'default_schema'
}

// Use in TableModel
Model dynamic_model {
type: 'table'
data_source_name: 'my_wh'
table_name: '${client_schema}.cities'
}

// Or in QueryModel
Model dynamic_query_model {
type: 'query'
data_source_name: 'my_wh'
query: @sql
select * from ${client_schema}.cities
;;
}

Then pass the schema in your embed payload:

embedded_payload = {
permissions: {},
user_attributes: {
schema: ['tenant_acme']
}
}

Supported variables reference

Holistics provides two built-in user attribute variables for dynamic database connections:

VariablePurposeUse in
H.current_user.data_sourceSwitch between different database connectionsDataset's data_source_name
H.current_user.schemaSwitch between schemas within the same databaseModel's table_name or query

You can use both variables together if your architecture requires switching both data sources and schemas:

embedded_payload = {
permissions: {},
user_attributes: {
data_source: ['customer_acme'],
schema: ['production']
}
}

Let us know what you think about this document :)