Skip to content
VizBolt

repository

Querying the Tableau Server repository safely (read-only, with examples)

Karan Arora · Founder · 7 min read · Last reviewed:

Tableau Server keeps a PostgreSQL database about itself — the repository, database name workgroup — and it is the best documentation your deployment will ever have, because it cannot be out of date. Every job, session, schedule, workbook, and sign-in is in there. It is also a production database that the server itself depends on, which is why most administrators either never touch it or touch it nervously.

Both extremes waste the asset. The repository can be read safely, with a short list of disciplines that cost nothing. This guide is those disciplines, plus enough example SQL to make the first session useful. It is also, not coincidentally, exactly how our own collector works — the rules below are the rules it ships with.

What the repository is, and is not

The repository stores metadata and operational history: content inventories, users, schedules, background jobs, HTTP request logs, audit events. It does not store your business data — extract contents live in files on disk, not in workgroup. What it does hold that deserves care: user names, email addresses, and the names of workbooks, projects and data sources. Nothing here is a row of your revenue table, but plenty of it is organizationally sensitive — which shapes the off-machine rules at the end of this guide.

Getting access, the documented way

Tableau provides a purpose-built account for this: the readonly user, enabled with TSM:

code
tsm data-access repository-access enable --repository-username readonly --repository-password <password>

Notes worth knowing before you run it:

  • The readonly account has SELECT grants and nothing else. The other documented account, tblwgadmin, is the superuser Tableau itself uses — never query with it, for the same reason you don't browse the web as root.
  • Remote connections reach the repository on port 8060 of the node running it, so a firewall rule scoped to the analyst machine is part of the setup — scoped, not open.
  • Enabling access is a TSM configuration change: plan it like one, in a maintenance window, and expect TSM to apply pending changes rather than assuming it is instant.

Any PostgreSQL client works from there. For a command line:

code
psql -h your-server -p 8060 -d workgroup -U readonly

For exploration with completion and saved queries, any SQL IDE with a PostgreSQL driver does the job. And Tableau itself is a legitimate client: custom administrative views are exactly this — a Tableau workbook pointed at workgroup through the PostgreSQL connector, which needs the PostgreSQL driver installed on the machine running Desktop. Connecting Tableau to its own repository feels circular the first time and quickly becomes the most natural way to share what you find with people who live in dashboards.

The session discipline

The readonly user's grants already prevent writes. The discipline below is defense in depth — it protects the repository from your tooling, your future self, and the query you didn't mean to run at that size:

sql
SET TRANSACTION READ ONLY;
SET statement_timeout = '30s';

The first line makes the session refuse any write, independent of what grants exist today or after an upgrade. The second is the one people skip: the repository serves Tableau Server in production, and a runaway analytical query holds resources the server wants. A statement timeout turns "my exploratory join was bigger than I thought" from an incident into an error message. Thirty seconds is generous for every query in this guide series; tune upward knowingly, not by default.

Three habits complete the discipline. Window every query on a timestamp (WHERE created_at >= NOW() - INTERVAL '30 days') rather than reading whole tables. Prefer aggregates over row dumps — you rarely need the rows, and the rows are where the sensitive names live. And keep transactions short: connect, query, disconnect, rather than holding a session open across a business day.

A map of the useful tables

The full schema is large, and Tableau publishes a data dictionary for all of it — versioned per release, so match it to your Server version (every table and column named in this guide is checked against the 2025.1 edition). In practice, reviews spend most of their time in a handful of tables:

| Table | What it answers | | --- | --- | | background_jobs | Every background job with queue and runtime timestamps — the backbone of failure and delay analysis | | http_requests | Request-level traffic: who loaded what, when, how long it took | | historical_events | The audit trail — sign-ins, views, publishes, downloads | | sites, projects, workbooks, views, datasources | The content inventory | | users, system_users | Accounts and identities (names and emails live here) | | schedules, tasks, subscriptions | What is set to run, when, and for whom | | extracts | Extract metadata for size and storage analysis |

There are also convenience views with underscore-prefixed names — _users, _views_stats and relatives — that pre-join common combinations for administrative reporting. They are handy for exploration; for anything you will automate, prefer the base tables and the data dictionary, so a version upgrade changes your queries on your schedule rather than its own.

The audit trail deserves a note of its own, because its shape trips people up. historical_events is a narrow fact table — the data dictionary calls it "the heart of the cluster of tables devoted to historical event auditing" — and the detail lives in hist_ dimension tables around it: hist_users, hist_workbooks, hist_views and relatives, joined by id. The hist_ tables are point-in-time copies, not live records — per the dictionary, they record what "was relevant at the time of the event." That is exactly what an audit trail should do, and exactly what a careless join to the live users table silently gets wrong. Sign-in analysis, view-access patterns and publish histories all start from this star; expect to spend your first session with the data dictionary open beside it.

Two practical cautions from the field, both observed rather than documented. http_requests is by far the largest table on busy estates and is trimmed aggressively by Tableau's own cleanup — window any query against it tightly, and check how much history yours actually holds before designing analysis around it. And every table's history is bounded by retention settings: SELECT MIN(created_at) against any table tells you the real window in one line.

First queries that earn their keep

A first session should answer real questions. Three starters, in increasing order of interest.

The estate at a glance — how much content exists, per site:

sql
SET TRANSACTION READ ONLY;

SELECT
  s.name                  AS site,
  COUNT(DISTINCT p.id)    AS projects,
  COUNT(DISTINCT w.id)    AS workbooks,
  COUNT(DISTINCT v.id)    AS views
FROM sites s
LEFT JOIN projects  p ON p.site_id = s.id
LEFT JOIN workbooks w ON w.site_id = s.id
LEFT JOIN views     v ON v.site_id = s.id
GROUP BY s.name
ORDER BY workbooks DESC;

What the platform is being asked to do — request volume by day, windowed tightly because this table is large:

sql
SELECT
  DATE_TRUNC('day', created_at) AS day,
  COUNT(*)                      AS requests
FROM http_requests
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY 1
ORDER BY 1;

And what is scheduled against those resources — tasks per schedule, with the priority that orders the queue:

sql
SELECT
  sch.name        AS schedule,
  sch.priority,
  COUNT(t.id)     AS tasks
FROM schedules sch
LEFT JOIN tasks t ON t.schedule_id = sch.id
GROUP BY sch.name, sch.priority
ORDER BY tasks DESC;

From here, the natural next steps are the deeper analyses this series covers: refresh failure concentration, queue-delay clustering, and backgrounder utilization — each of them a handful of queries against background_jobs using exactly this session discipline. Structurally, our audit of a full Tableau deployment is this same practice at scale, with a rule library behind it.

Surviving upgrades

The repository schema is Tableau's, not yours, and Tableau changes it between versions — tables gain columns, views get reshaped, and nothing about your queries is guaranteed across an upgrade. The data dictionary is published per version, which is the tell: treat your saved queries the way you treat any dependency on someone else's schema. Concretely, that means three habits. Keep the queries in version control with the server version they were written against. After every upgrade, re-run the set against the new version before trusting any number they produce — a renamed column that errors loudly is the good outcome; a semantic change that keeps the same name is the one to hunt for. And prefer base tables over the underscore convenience views for anything automated, precisely because the convenience views are the more likely to be reshaped for Tableau's own purposes.

The off-machine rules

Everything above concerns reading safely. The other half of repository discipline is what leaves the machine afterwards, because query results carry the sensitive part: user names, email addresses, content names.

The rules we run our own collector under, and recommend generally: aggregate before anything leaves the box — counts, durations, percentiles, never raw rows. Replace object names with codes if results must travel, and keep the code-to-name key where the data came from. And make transfer a human decision: a file someone reviews and sends, not a pipe that streams. A repository analysis that follows those three rules can be shared with an outside party — or with us — without your data ever really leaving home. That is not a compliance nicety; it is what makes the analysis possible at all in organizations where "export the user table" is correctly a firing offense.

Tableau Cloud has no repository

None of the above applies to Tableau Cloud — there is no workgroup database to reach, by design. The equivalents live in the Admin Insights project and the Metadata API, which cover much of the same ground in a different shape. That mapping is its own guide.

Small rules, compounding returns

Read-only user, read-only transaction, statement timeout, tight windows, aggregates out. Five rules, each one line or one habit, and together they turn the repository from the database everyone is afraid of into the instrument every serious Tableau review is built on. The server has been keeping honest records all along — as far back as its retention settings allow. It is only polite to read them carefully.