DEV Community

Jung Kim
Jung Kim

Posted on

The Easiest Way to Snapshot Tableau's PostgreSQL Repository Over Time

Tableau's PostgreSQL repository tracks event history well — historical_events will tell you plenty about what happened and when. But content and state tables like _workbooks and _datasources only reflect current state; they don't retain past values for things like storage size or content counts. Getting a trend line out of that might sound like it needs a script, a cron job, or a separate table to accumulate snapshots over time. It doesn't — Tableau Server can do all of that for you.

The pattern

  1. Write a SQL query that returns the point-in-time metric you care about (storage, content counts, whatever).
  2. Publish it to Tableau Server as an extract.
  3. Set the extract's refresh type to incremental refresh, instead of full refresh.
  4. Put it on a schedule — daily, weekly, monthly, whatever cadence matches how fast the thing you're tracking actually changes.

Each scheduled run appends new rows instead of overwriting the extract, so the extract itself becomes your history table. No external script, no cron job, no separate database to maintain — Tableau Server's own scheduler is doing all the work you'd otherwise build yourself. (Tableau's own docs on configuring incremental refresh are worth a look if you haven't set one up before.)

The use case

I use this to track server storage over time (more on that in another post), but the pattern generalizes to almost any "how has this changed" question you can answer with a single query: content counts, stale content trends, license utilization — anything where you'd otherwise be tempted to stand up a mini data pipeline just to get a time series.

Things to know before you use this

  • Incremental refresh only works cleanly if each run is genuinely additive. The query needs to produce new rows each time (e.g., a snapshot keyed to CURRENT_DATE), not update existing ones. If your query's output could change retroactively for a past date, incremental refresh will get out of sync with reality — full refresh or a different approach is a better fit in that case.
  • This trades granularity for simplicity. You get whatever snapshot frequency your schedule uses — daily is common — not a continuous audit trail of every change as it happens. For most trend-watching use cases that's a fine tradeoff; if you need to catch every individual event, you're back to querying historical_events directly instead of snapshotting a summary.
  • Keep the query itself simple. The whole appeal of this pattern is that Tableau Server does the heavy lifting on scheduling. If the underlying query gets complicated enough that it needs its own maintenance, some of that simplicity advantage starts to erode.

Top comments (0)