We have a tendency to answer questions of multitenancy in Tableau swiftly with switching between Sites, which are the virtual tenements for your Tableau tenants. But Sites are the simple part of the equation; when there is a need for multitenancy in Tableau, there is most likely existing multitenancy in the data systems Tableau must connect to. I’m going to dive into the diverse ways that customers corral their data and outline all the tenets of deploying effectively from a single template to all your tenants.
The database world is full of terminology that is used differently by each vendor, so I’m going to use some wonderfully generic terms to describe the situations we commonly see. In this post, a database server is the thing you type credentials into in Tableau during “Connect to Data”, referenced by a single domain name or IP address. A logical partition is a grouping of tables (and so forth) on that database server. A schema is the organization and structure of those tables in the logical partition.
Central Tenet: The schemas must match between logical partitions to use templates
The basic need for publishing from a template in Tableau is that the schema be identical (or near enough) between each logical partition. If there is a table called “DataFacts” in logical partition 1 with three columns – A, B, C – then there better be a table called “DataFacts” with three columns A, B, C over in logical partition 2.
If you have this situation, all you have to do is build your Tableau workbook or datasource on one of the logical partitions, then save the TWB or TDS file. You will build a process to take this template, make any necessary transformations, then publish via the REST API — all of which is described in this post.
“Virtual” multitenancy: 1 database server, 1 logical partition
Some customers store all of their customer data in a single logical partition, with a column in every table that identifies which of the tenants the data belongs to. Often this is the case in a reporting data warehouse, but your operational system may also exist this way. It is more rare in industries that have strict regulations around personal identifying information, such as healthcare.
Solution: One Workbook with Row Level Security, published to each Tableau Site
A simple example is a “customer_ID” column on every row of data in the database. Using Row Level Security, join in the “security_table” on “customer_ID”, then put your security calculation of “[Username] = USERNAME()” as a data source filter. This will always filter the data down to just those rows that the user should see.
The convenient thing is that since all of the tenants are in the same database, you will just need to publish the workbook or data source to each Tableau Site, with no changes.
Standard SaaS / HIPAA-Compliant: 1 database server, 1 logical partition per tenant
If you have a single database server, with an identical logical partition per tenant, then you your prerequisite is some kind of table that records the logical partition name for each tenant ID. Ideally, you will have named your Tableau Sites to match your tenant IDs, but if not, you’ll need a way to match the Site names to the tenant IDs.
Solution: Programmatically publish from a template, changing the connection XML to point to the correct logical partition
Publishing Datasources and Workbooks to Multiple Sites is the guide for how to do this; it outlines the process in the XML and shows how to use the tableau_rest_api Python library, which has the XML modification built in. You are welcome to script out the XML change in any language, and we’ve seen customers do it all different ways.
Multiple database servers, 1 logical partition per tenant
If your logical partitions are spread among multiple database servers, you need a mapping of the tenant ID to the logical partition name and the server address. There’s two ways you can go about this process
Solution 1: Modify the XML for Logical Partition Name and Server Address
If you are doing XML modification, you might as well change both while you are at i, they are just properties in the same tag. However, if you want to use “Tableau supported” methods as much as possible, you can instead do
Solution 2: Modify the XML for Logical Partition Name, then use REST API to Update the connection
Basically this combines the SaaS method with the “Multiple database server, 1 logical partition per server” method below. I would just do it all in the XML.
Multiple database servers, 1 logical partition per server
If you have multiple database servers but the same logical partition name on each of them, with some arbitrary number of tenants spread among the servers, then you simply need a mapping of the tenants to the correct database server connection.
Solution: Use REST API “Update Datasource Connection” or “Update Workbook Connection” Method
The Tableau REST API includes methods called “Update Datasource Connection” and “Update Workbook Connection” which let you change the database server address of a published data source or workbook. Your script should look at the mapping of tenants to connection addresses and:
- Publish the template workbook to the correct site
- Issue the Update Datasource/Workbook Connection command to point the connection to the correct database server address