Data Quality·8 min read·Mar 19, 2026

Tableau Workbook Health Check: What to Audit Before You Migrate

Unused calculated fields, circular dependencies, and nested LOD expressions discovered mid-migration will cost you double the time. Audit first.

You know the workbook has problems. The dashboards load slowly, some fields haven't been used in two years, and there's a calculated field that references another calculated field that references three more. But when you look at the field list, everything looks fine. Nothing is obviously broken.

Tableau won't tell you any of this. There's no built-in linter, no health score, no way to identify unused fields or trace circular dependencies from the UI. You have to discover these things the hard way, usually in the middle of a migration, when fixing them becomes doubly disruptive.

Auditing a Tableau workbook before you migrate, or before a major refactor, is the single highest-leverage thing you can do to reduce migration risk. Here's what a proper audit should check and why each issue matters.

Why Tableau Workbooks Get Messy

Tableau's calculated field model is optimized for flexibility, not maintainability. There's no enforced naming convention, no deprecation mechanism, no warning when you create a field that nothing uses, and no constraint on nesting depth. You can build a field that references a field that references a field ten levels deep and Tableau will render it without complaint.

Over time, workbooks accumulate:

  • Fields created for one-off analyses that were never removed
  • Fields renamed but still referenced by their old internal IDs in other fields
  • LOD expressions nested inside other LOD expressions
  • Long IF/ELSEIF chains that could be simplified to a CASE
  • Division expressions missing NULLIF() or ZN() protection
  • DATETRUNC() or DATEDIFF() calls with hardcoded date parts that should be parameters

None of these are obvious from the field list. They require systematically parsing every formula and checking it against a set of rules.

The 8 Checks That Matter

01

Circular dependencies

Error

Field A uses Field B, Field B uses Field C, Field C uses Field A. Tableau handles these gracefully in the UI, but they're a silent trap: if you migrate them to dbt as written, you'll get a circular dependency error on the first dbt run. These need to be resolved before migration, not during.

02

Unused calculated fields

Warning

Fields that aren't referenced by any sheet, dashboard, or other calculated field. These are migration dead weight: you'd be translating SQL for logic that doesn't power anything. On average, complex legacy workbooks have 20–30% unused fields. Finding and removing them first reduces migration scope significantly.

03

Division without null protection

Warning

Any expression of the form [A] / [B] where B could be zero or null. In SQL this throws a divide-by-zero error. Tableau silently returns null, so this is often invisible until you try to run the migrated SQL. Every division expression should be ZN() or NULLIF()-protected before migration.

04

Deep nesting (4+ levels)

Warning

A field that references a field that references a field that references another field. At four levels or more, formulas become very difficult to trace and debug. In dbt, deep nesting usually indicates a missing intermediate model; each level of nesting should ideally be a separate, named model.

05

Nested LOD expressions

Warning

A FIXED LOD inside another FIXED LOD. These are the hardest Tableau expressions to migrate: each LOD needs a separate CTE, and nested LODs mean the outer CTE references the inner CTE, which requires careful grain management in the resulting SQL. Flag these early.

06

Non-additive window functions

Info

RUNNING_SUM, RANK, INDEX, WINDOW_AVG and similar table calculations. These don't have a direct SQL equivalent and require a window function with the right PARTITION BY / ORDER BY. That context lives in the visualization, not the formula. Flag these so the migration plan accounts for the manual rewrite time.

07

Long IF chains (5+ branches)

Info

IF / ELSEIF chains with five or more conditions are a maintenance and readability problem. In SQL they should be CASE WHEN. They're often also a signal that a lookup table would be more appropriate. A 20-branch IF chain mapping region codes to region names belongs in a dim table, not a calc field.

08

Hardcoded DATETRUNC values

Info

DATETRUNC('month', [Date]) hardcoded to a specific date part is often a business rule that should be a parameter. If the granularity ever needs to change, it requires touching every field that contains that hardcode. Flag these so they can be parameterized during the migration.

The Health Score Formula

Once you've run all eight checks, you need a way to communicate the overall state of the workbook to stakeholders who aren't going to read a list of 47 flagged fields. A health score does this.

# Health score formula
score = 100
score -= (errors × 10)
score -= (warnings × 3)
score -= (info × 1)
score = max(0, min(100, score))

Errors (circular dependencies) are weighted highest: they will break a migration outright. Warnings are medium weight and will likely produce incorrect SQL or require significant manual cleanup. Info items are improvement opportunities that won't break anything but should be addressed before a migration adds new complexity on top of them.

A score above 80 is workbook that's ready to migrate with manageable cleanup. 60–80 means there's meaningful cleanup work that will pay off in migration time. Below 60, consider doing a workbook rationalization pass before migration: translating a mess into a different kind of mess doesn't help.

Per-Field Complexity Scoring

Beyond the workbook-level health score, each calculated field gets an individual complexity score from 0 to 100. This is useful for migration planning: it helps you identify which fields will take minutes versus hours to migrate correctly.

0–25
Simple

Basic arithmetic, string operations, simple IF

26–50
Moderate

Date functions, multi-level nesting, parameters

51–75
Complex

LOD expressions, nested conditionals, table calcs

76–100
Critical

Nested LODs, circular refs, deep nesting chains

Sort your field list by complexity score descending before starting a migration. The critical and complex fields are where you need senior AE time. The simple and moderate ones can often be translated automatically or by a junior engineer following the pattern.

Running an Instant Audit

I built tableautodbt.com/audit to run all eight checks automatically against any .twb file. Nothing leaves your browser. Drop the file, get back a full audit report with:

  • Overall health score (0–100)
  • Issue count by severity: errors, warnings, info
  • Per-field complexity ratings with the specific issues detected
  • Every issue explained with what it means for migration and how to fix it
  • Export to Markdown, JSON, or Confluence

The typical workflow: run the audit, export the report, fix the errors and high-severity warnings, run the audit again. Once the score is above 80, the workbook is in reasonable shape to start the migration with the dbt converter.

Audit your workbook before you migrate

Drop a .twb and get a full health report in seconds: unused fields, circular deps, LOD issues, complexity scores. Free, browser-based.

tableautodbt.com/audit →
Justin Leu

Justin Leu

Data & BI Consultant · San Francisco

17+ years helping companies like Google, Pinterest, Salesforce, and United Healthgroup turn raw data into actionable business intelligence. I write about BI strategy, data infrastructure, and the practical side of analytics.

Work with me →