Skip to content

Insights: live dashboards on your warehouse

Build live, governed dashboards straight on top of your Databricks SQL warehouse — a layout of cards, each backed by a SQL query or a published metric, with no data ingestion and no copies to keep in sync.

Insights is the platform's tell-me-numbers surface — where a business user goes to see how the company is doing right now, on data that never left the warehouse.

Card types8
Data sourcesSQL · Metric
EngineDatabricks SQL · live
Result cachePostgres · 24 h TTL

When to choose this

  • Stand up a dashboard fast


    Start from a template — KPI overview, time series, data explorer — or describe what you want and let AI generate one.

  • Embed governed metrics


    Drop a published metric onto a card with one click: no SQL rewrite, no drift, lineage back to the definition.

  • Mix governed and ad-hoc


    Metric-backed cards for the numbers that matter, ad-hoc SQL for exploration — on the same dashboard.

  • Gate it before sharing


    Send a dashboard for review; an approver signs off in their Tasks inbox; it moves draft → under review → approved.

When not to reach for Insights

  • Defining the KPIs themselves — governance, versioning, ownership → use Metrics.
  • Embedding a Databricks AI/BI (Lakeview) dashboard → use Dashboards.
  • Firing when a number crosses a threshold → use Alerts.

How a card renders

Every card declares a data source. A SQL card renders its filters into parameters and runs your query; a metric card hands off to the published metric. Either way the query runs live on your Databricks warehouse, the result is cached, and the card draws itself.

flowchart LR
    CARD["Card"] --> DS{"Data<br/>source"}
    DS -->|sql| SQL["Render filters<br/>· read-only validate"]
    DS -->|metric_ref| MET["Metric dispatcher<br/>published version"]
    SQL --> DBX(["Databricks<br/>SQL warehouse"])
    MET --> DBX
    DBX --> CACHE[("Result cache<br/>Postgres · TTL cascade")]
    CACHE --> VIEW["Rendered card<br/>KPI · chart · table · matrix · multi-metric"]
    classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
    class DBX accent

Figure 1 — A SQL card and a metric card both resolve to a live query on your Databricks warehouse; the result is cached in Postgres and the card renders from cache until its TTL expires or you refresh. (Metric cards use the Metrics module's own cache under the same contract.)

Why teams reach for this

The numbers are live on your own warehouse — no ingestion, no copy, no nightly ETL to drift out of date. Governed metrics keep the definitions consistent, the result cache keeps a busy dashboard fast, and per-user OAuth means every query runs — and is audited — under the viewer's own Databricks identity.

Card types

Type Use it for Backing
Metric Single KPI, with optional comparison or trend. Five layouts: simple, sparkline, target, segmented (2–3 sub-KPIs), bars. SQL or metric.
Chart Time series, bar (vertical or horizontal), area, line, combo (bar + line), pie/donut, treemap, and sankey (flow). Bar, area and combo can be grouped, stacked, or 100% stacked. Y-axis formatting, custom tooltip, value labels, axis titles, a legend you can place top, bottom, left or right (pie and donut default to the bottom; horizontal bars offer top or bottom only). Row order (any column, including a measure — e.g. biggest bars first — with multi-level tie-breakers) is set under Sorting on the card editor's Build tab; it requires edit permission on the dashboard. Chart Colors (Format tab) lists what the chart colours, each with the colour it uses today: a pie, donut or treemap lists its categories, a chart split by a column lists that column's values, and other charts list their measures. Type a hex colour next to a name to override it; the colour follows the name, not its position, so it stays put when the data is sorted differently. Names without an override use the dashboard palette. SQL or metric. Sankey reads one row per flow (from, to, amount) and is available on SQL cards only.
Table Tabular display with column-level number formatting (including a per-column override on top of the card's default), per-column filtering, and click-to-sort. The order the table opens in is set under Sorting on the card editor's Build tab, with the same sort levels a chart uses (it requires edit permission on the dashboard). Viewers sort on top of it by clicking headers or with the card's Sort control, and on a report that order is kept for each viewer alone (see A card's view options). Click a header to add it as a sort key (ascending), click again to reverse it, a third click drops it — later clicks on other columns add secondary/tertiary keys (max 3) rather than replacing the first, so ties on the primary column break on the next one you clicked. While the table is in its saved order, clicking a column outside that order sorts by that column alone, and clicking the saved order's only column reverses it. Dropping every key you clicked returns the table to its saved order, and so does Reset to report default in the card's view options. In design mode a header click isn't kept: while it replaces the saved order, the card's header shows Saved order; click it to go back. Column order can be set two ways: the Column Order list on the card editor's Build tab (which also hides and renames columns), or — if you can edit the dashboard — by dragging a column's header directly on the card. Hover a header to reveal its drag handle; the new order saves as soon as you drop it. Rows can be grouped by up to three columns. SQL or metric.
Matrix Full pivot table: nested row and column dimensions, several measures, totals and subtotals, percent-of modes, top-N limits, and numeric / heatmap / data-bar display. See Pivot matrix cards. SQL or metric.
Multi-metric One query → grid of KPI tiles, each tile mapped to a column with its own format, trend, good direction and icon. SQL or metric.
Hero One headline figure that tells its own story: the value, up to two comparisons (the previous period, a target or a reference, each shown as a percentage change, a difference or both), optional good/bad thresholds on the first comparison's change, and a narrative around the figures. SQL or metric. On a metric card, a comparison can be the metric's own previous period.
Scorecard A compact grid of KPIs in up to six labelled groups of up to five rows each, every row a value column with an optional comparison column. One comparison label (for example Target) names every row's comparison. When the rows compare with different bases, say vs target for revenue and vs last year for footfall, give each row its own Comparison base: the row shows it under its label, and its change badge names it. Format, good direction and change unit are set once for the block and can be overridden per row. SQL or metric.
Signal One series against a reference per period (for example revenue against target), led by the latest period or the average over the periods, with a one-line description, a narrative, and up to three actions to take. An action marked AI-suggested may not contain digits, so it never reads as a computed figure. SQL or metric.

A Hero, Scorecard or Signal card is set up in the card editor's Build tab like any other card: pick the type, and the tab lists the block's settings. When the block reads good or bad (its Status, a hero's thresholds, a scorecard's defaults) is on the Analyze tab, and its number format on Format. Columns are picked from the query's result (run the query first). The comparisons, groups, rows and actions are added one at a time, up to the block's limit. A narrative is written in paragraphs, headings, captions and lists; the block's figures are inserted from a list as pills, never typed, and are filled in every time the card is read. They are written the way the block shows its figures, in its number format and the organisation's number locale: a revenue in euros reads "€ 90.000,00", a percentage change "+12,5%" with its sign, and a difference "-€ 2.000,00". On a block whose value is a percentage, a difference reads in percentage points. So does the change, wherever the block's change badge shows points: a conversion rate of 22,64 % against 19,65 % reads "+3,0 pp" on the badge and in the sentence, not "+15,2%". Set the block's change unit (or a hero comparison's Show) to the relative change, or a hero comparison to show both, and the sentence writes the relative change; the difference figure then still reads in points. On a block in a currency or a plain number, the change stays the relative change in the sentence, whichever unit the badge shows. Percentage points are written "%-punt" when the organisation's number locale is Dutch, and "pp" for every other locale, as the badge shows them. A figure brings its own unit, so a "%" typed right after the change is left out. A setting the block cannot save is marked on its own field, before or when you save. The preview shows the block's figures once the card is saved; until then it shows the query's first rows.

How a KPI shows its change

A Metric card with a comparison column, or a Sparkline or Bars layout (which compare the last point with the one before), shows the change next to the number. A multi-metric tile with a trend column does the same. On a Metric card, the trend format and comparison label are under Trend on the card editor's Format tab, and the good direction is under Status on its Analyze tab. On a multi-metric card they are set on each tile, on the Build tab:

Setting What it does
Good direction Higher is better (the default), Lower is better for costs, error rates or a claim ratio, or Neutral for a number such as headcount. A rise on a lower-is-better KPI shows red. A neutral change shows grey.
Trend Format (Metric card) Percent Change, Absolute Change, Raw Value, or Percent and absolute, which shows both: +12.6% (+€16,000). A multi-metric tile always shows both, except a Percent tile, which shows only the change in percentage points.
Comparison label Replaces the "vs" caption, for example "vs last year". Leave it empty to keep the default.
Icon (multi-metric tile) A small icon before the tile's label.

Next to the arrow, a tick or a cross says whether the change is favourable, so the colour is not the only signal. A value formatted as a percentage changes in percentage points: 6.2% to 6.8% reads +0.6 pp, not +9.7%. No change at all reads grey, not green.

HERC can set all of these for you. Tell it that a rising claim ratio is bad news, and it makes that card, or that tile on a multi-metric card, Lower is better. It can also set the trend format, the comparison label, a tile's icon, and the bands where a change turns good or bad.

A sparkline KPI and a month filter

A Sparkline KPI reads a pick on a filter over its Trend X axis column (a filter with that name, or on that column) as the period to show, not as a filter on its rows. The line keeps every period, and:

  • the number is the period you picked, and the change compares it with the period before;
  • the caption names both, for example Mar 2026 vs Feb 2026;
  • with several periods picked, it shows the latest of them and marks the others on the line. It never adds them up;
  • with nothing picked, it shows the latest period.

Switching periods doesn't run the query again. Hover the line to see each period's value.

The card reads the pick as a row filter instead when its SQL places the filter itself ({{Maand}}), and when it is built on a saved query.

By default the line follows the change: green when it improves, amber or red when it worsens, and the other way round when lower is better. To fix its colour, set Line colour under KPI layout in the card editor.

Which series a chart draws

A chart draws the series saved with the card: the columns ticked under Y Axis Columns on the card editor's Build tab, or the bar and line columns of a combo chart. A chart that can draw only one series draws it. A chart with two or more series to choose from and none saved draws nothing until someone picks: the card asks for a pick, and its Series pill lists the candidates.

  • Viewing a dashboard, a pick from the Series pill is your own. Nobody else sees it, and nothing is saved. It stays while you re-run the card, change a filter or the granularity, or the card's query changes. A series the query no longer returns drops out of it. When the card's saved series change, for example after a HERC suggestion is applied, the saved series are drawn again.
  • In Design mode, and in the card editor's preview, the Series pill sets the card's series, the same as ticking the Y Axis boxes. Every viewer then sees what you picked. With nothing picked, the card tells you to pick the series viewers should see.
  • A combo chart draws a bar or a line for each ticked series. Untick a Y Axis box to take that series out of the chart, including one HERC put on the bars or the lines.
  • A series the query no longer returns, for example after you edit the SQL, is left out of the chart, its legend and the Series pill. Under Y Axis Columns the card editor names it, with Remove from series to take it out of the card. Nothing is removed on its own: while the query fails or has not run yet, the saved series stay, and the series is drawn again once the query returns it.

Pie, donut and treemap charts plot one measure: the first saved series. When more are saved, the chart says how many it leaves out.

A card's view options

A chart or table card's header ends in a View options button (the sliders icon). It holds:

  • Sort: the column the card is ordered by, and an arrow that flips its direction. Report default is the order the author set. On a report, your pick is kept in your saved view of that report, for you alone, from the moment you make it; a table's header clicks are kept the same way. The arrow flips only the first column, so the further columns a table's header clicks added stay.
  • Granularity, Series and Date density on a chart: the columns its axis groups by, the series it draws and the date level its axis counts in. On a report these are yours as well, kept in your saved view like your sort, and they never change the chart for anyone else. A pick that no longer fits the card, for example a column the query stopped returning, makes way for the report's own. A pick also lapses when the author changes that control's default: the card opens on the report's new default, and your old pick is dropped the next time you change one of these on that card. If you can edit the report, the menu says that these controls change only your own view and that the report's defaults are set in Design mode.
  • Card filters past two. A card with more than two filters keeps the ones with a value in its header and moves the others here. When the menu holds nothing else, the button names them, for example 2 more filters. A filter you change in the header stays there until you close the menu, or until you are done with the card: the pointer is off it and you are no longer typing in it. It never moves while you use it.

While your sort, grouping, series or date level differs from the report's, the button shows a dot, and Reset to report default takes them all back. Reset my view drops them along with your filters; Save my view keeps them.

When the author publishes a new version of the report:

  • Each card keeps your sort and picks, also when the author reworked the card. A sort column the card no longer returns is ignored; with none left, the card opens in the report's order.
  • A pick whose default the author changed lapses, as above.
  • A sort or pick for a card the author archived is kept until your view is next saved, and then dropped. A card the author restores before that comes back with your sort and picks; one restored after it comes back with the report's defaults.

In design mode the menu has no Sort: the author sets the card's order under Sorting in the card editor. There, Granularity, Series and Date density set the card's defaults, which every reader opens on.

Ways to back a card

Every card carries a data source discriminator, and a single dashboard can mix them:

  • sql — you write Databricks SQL. The platform parameterises filters, runs the SQL through a read-only validator, executes it against the warehouse, and renders the result.
  • metric_ref — you pick a published metric on the same connection; the platform runs the metric's currently-published version and renders it. Switching grain or compare-period is a chip on the card — the SQL is owned by the metric, not the dashboard.
  • From Saved Query — you pick a saved query with an active version; the card follows that version, on the query's own connection. Show chooses between All rows (the query's result as it is — for a table, chart or map) and Summary (totals over those rows — for a KPI): count rows, count distinct, sum, average, minimum or maximum of a column, optionally grouped by up to three columns (grouped and sorted in the order you pick them) for a chart or table. The dashboard's filters narrow the rows before they are summarised. On Azure SQL and Fabric — for these cards and for cards with their own SQL — a filter applies to a column the query names in its SELECT list (not SELECT *), and not to a query that keeps only its first rows (TOP, OFFSET) or ranks or totals rows with a window function (OVER); the card says when a page filter doesn't apply. The query itself never changes. Summaries run on Databricks, PostgreSQL, Azure SQL and Fabric connections. On Azure SQL and Fabric every column of the query needs a name (COUNT(*) AS total, not a bare COUNT(*)); the card editor tells you which one when it doesn't.

The picker only offers what will work

The From Metric tab of the add-card modal lists only active, published metrics whose connection matches the dashboard's — you can't accidentally pair an Acme prod metric onto an Acme staging dashboard. The full contract is in Backing a card with a metric.

What Insights looks like

Surface Where What you see
List /insights Sidebar (search + status checkboxes + tag filter) on the left, dashboard cards on the right with status badges (Draft / Under review / Approved) and tag pills. A Type column (Dashboard / Action list) can be filtered like Status. Once the metadata engine is connected, a platform-provisioned Metadata Engine Overview dashboard is pinned first with a System badge — see below.
Create /insights/new Three on-ramps: pick a template, ask AI to generate one, or start blank.
Viewer /insights/{id} Multi-page tabs, filter bar, cards in their layout. Edit toggles inline edit-in-place. Submit for review opens the workflow trigger.
Editor /insights/{id}/edit Pages, sections, cards, layout picker, filter config, AI sidebar for editing card SQL / metric binding.
Card edit panel Viewer in edit mode → click a card The right-hand panel opens the full edit form beside the live dashboard, 600 px wide by default, and the card you are editing is outlined on the dashboard. Drag the panel's left edge, or focus that edge and use the arrow keys, to size it between 480 and 960 px; double-click the edge or press Enter on it to reset. Opening another section of the panel while you edit, such as Your access, folds the editor into a heading at the top of the panel. Your unsaved changes stay, and clicking the heading brings the editor back.
Saved queries /data-catalog/queries (Data Catalog in the sidebar; /insights/queries redirects there) The saved warehouse SQL your flows run, with the domain accountable for each query. Domain stewards also see the other owners' private queries they may file. See Saved queries.

A status notice that opens on its own (e.g. a "these cards are hidden" warning) closes itself after a few seconds so it doesn't sit over the page — hover or focus it to keep it open while reading. Once you've seen it, it won't pop open again on your next visit for 24 hours; the coloured indicator on its label stays visible either way, so nothing is actually hidden. A notice that names something you must resolve before proceeding never closes on its own and reopens every visit until the underlying issue is fixed.

The platform-provisioned overview dashboard. The first time anyone loads /insights after your metadata engine has a working connection and at least one synced, non-empty catalog, DataHub automatically creates and pins Metadata Engine Overview — a two-page dashboard (Insights KPIs, Alerts KPIs) marked with a System badge (on both the list and the dashboard's own page) so it reads as platform-generated rather than a colleague's dashboard. From that point on it behaves like any other dashboard — edit it, add cards, export it — except it can't be archived (there is only ever one, so removing it would mean losing it for good). If no dashboards exist yet and the metadata engine isn't connected, the empty list instead shows a Connect metadata engine button (visible only to whoever holds the metadata-engine connection role) that opens the connection setup flow.

The Total Dashboards / Approved / Drafts / Total Sections counts at the top of /insights don't include this platform-provisioned dashboard — they track what your team has authored. In a brand-new org whose only dashboard is this one, the counts read 0 with a short note explaining why, rather than silently disagreeing with the row visibly sitting in the table below.

Setup — what an admin does once

Prereq Where Why
Databricks integration /admin/integrations → Databricks The SQL warehouse Insights queries against. Use Databricks per-user OAuth for per-user RLS + per-user audit.
AI provider key /admin/integrations → AI Provider Keys Powers the AI dashboard generator and the in-card Ask AI panel.
Roles /rolegroups insights.read to view; insights.manage to author dashboards / cards / ad-hoc queries / import / export / submit for review.
(Optional) Workflow /admin/workflows If you want a review gate before publishing, configure a workflow for insight_dashboard. The platform seeds a sane default.

Building a dashboard

  1. Create. /insights → New. Pick one of the three on-ramps below.
  2. Add cards. Choose a card type, then back it From SQL or From Metric.
  3. Configure. Set display config per card type. Build the query in the guided builder (catalog → schema → table → columns) or drop to raw SQL. Under Header you also choose how the card's header reads — Title only, Title with icon (a badge showing the card's type), or Title with icon and divider (the same badge plus a rule separating header from body). It is a per-card setting, so a dashboard can give its headline cards a divider and leave the rest plain. Multi-metric cards offer the first two: their fused metric strip already draws that rule itself.
  4. Filter. Add dashboard-level global filters and per-card overrides. In Design mode the report filters show as cards, two per row on a wide enough panel. Each card starts collapsed and names its type and its source: a connection column, a catalog card's column, or a model field. A collapsed card still flags anything that needs fixing. Drag a card by its handle to change the order the filter bar lists them in. A typed field (a name, a minimum or maximum, an options query) is saved when you leave it or press Enter, so the cards don't re-run on every keystroke.
  5. Arrange. Group cards into sections, choose a layout, split across pages. In Design mode, rename a page with the rename button on its tab, or double-click the tab: Enter or leaving the field saves the name, and Escape keeps the old one. In edit mode, drag a card's handle (hover over its top-left corner) to reorder it within a section or drop it into another. A row can be Full Width, Two Columns, Three Columns, Four Columns, 1/2 + 1/4 + 1/4, or Columns (2–6), which sets a column count from two to six with the − and + buttons beside the picker. Columns rows keep their columns equal width and narrow to two columns on a smaller screen and one on a phone. When a row holds more cards than its layout has room for, Design mode names the hidden cards above the row, so you can archive some, pick a wider layout or stack another card in a column. In Design mode, drag the handle under a row to set its height, or focus the handle and use the arrow keys (Shift+arrow takes bigger steps, Home and End jump to the shortest and tallest height). Double-click the handle, press Enter on it or choose Auto height to let the tallest card set the height again. The cards fit the height you set: a chart grows or shrinks with it, a table or long list scrolls inside its card (a table keeps its column headers in view), and a KPI card sits in the middle of the row. A pie, treemap, sankey or horizontal bar chart keeps its own size for now, and its card scrolls when the row is shorter. Cards per column, above the row, stacks up to four cards in a column, top to bottom, so a tall chart can sit beside two KPI cards on top of each other. A row with a stacked column never gets shorter than its KPI cards need to show their figure and trend, so the handle stops there. A column gives up a place only while its last place is empty; otherwise you are asked to move or archive a card first, so a card never moves to another column by itself. On a narrow screen the row keeps its automatic height. An AI assistant connected over MCP can set a row's height and stacks when it creates a dashboard, within the same limits (a height of 120 to 1,600 pixels, one to four cards per column).
  6. Review & share. Submit for review if a workflow is configured, or export the dashboard to move it to another environment.

Pick KPI overview, time series, or data explorer — pre-wired layouts you adjust to your columns. Or pick a story template, whose data you bind before the dashboard is created.

Describe the dashboard ("Sales pipeline by stage, last 90 days, with conversion KPIs"). The insights agent reads your connection's published metrics first and only writes SQL to fill the gaps, validating every generated query before it lands.

Start empty and add cards one by one.

An AI assistant can also change an existing report: its pages, page filters and cards, including a table's column formats and grouping. It works on the report's draft and can send it for review. Readers see the published version until a person in the reviewing group approves it. See AI platform.

Story templates

A story template creates a dashboard that already tells a story. Today there is one, Performance coach:

  • a headline result against last year and target;
  • a scorecard of three to six groups (optional);
  • three to five signals, each calling out what to watch.

Unlike a regular template, you bind its data before the dashboard is created.

  1. Pick it. On the template step, its tile shows a preview drawn from sample figures, so you see the dashboard's shape before you choose it.
  2. Configure. Name the dashboard, choose its domain and its data connection. A story template always reads from one connection, so the connection is required here.
  3. Bind the slots. Each slot shows what it needs (for example, a weekly figure). Give it a published metric or a saved query, then the labels its card needs, such as a signal's reference column and its name. A metric fills in its own measure and period column. Signals can be added up to five and removed down to three.

Each signal also has a Format: a number, currency or percentage, so an average basket reads "€ 104,89" and an NPS "42", not "104,89%". The change badge follows the format: an amount changes in euros ("-€ 2,66"), a number by its difference ("+3"), and only a percentage in percentage points ("+1,2 pp"). A sentence on the card that states an amount's or a number's change gives it as a percentage of the reference. Left on Automatic, the format is read from the column names, then the signal's title (avg_basket_eur is an amount, conversion_pct a percentage, nps_score a number). When they say nothing, the signal is a percentage.

A signal on a dashboard created before this change keeps its format. To fix one, open the card's Format tab and set its format; for an amount or a number, also set Show the change as to Difference under Status on the Analyze tab: left on Automatic, an amount's change is shown as a percentage. 4. Name the filter column. This is the column your sources share for the store or department filter every viewer uses. You can also add the query that lists the values viewers can choose from. If you leave both blank and let HERC fill the slots, HERC fills them in for you. 5. Create. The side card counts the required slots bound and lists what is still needed; New Dashboard stays disabled until every required slot is bound. The dashboard opens in design mode.

flowchart LR
    A[Pick story template] --> B[Name, domain, connection]
    B --> C[Bind each slot]
    C -->|required slots bound| D[Create dashboard]
    D --> E[Opens in design mode]
    D:::accent
    classDef accent fill:#ff8400,stroke:#e67700,color:#fff

A slot left empty on purpose

An optional slot you leave unbound becomes a card that says Choose a metric for …. The bind step tells you how many slots will start this way. Anyone who can edit the dashboard sees Bind a source on that card. It opens the card editor with the slot's format, direction and period already set; saving turns the placeholder into the real card. Other viewers see a note that an editor can bind it.

When the server refuses

If a source doesn't fit its slot (for example, a metric read per month where the slot needs weeks), nothing is created. The bind step says why and marks the slot it refers to.

Let HERC fill the slots

Under a story template's tile, Fill with AI lets HERC propose a source for every slot. You still review each slot, and create the dashboard yourself.

  1. Brief. Tell HERC the goal, the audience and the key metrics. Every field is optional.
  2. Tables. Choose a data connection and up to 10 tables, then Fill the slots. HERC reads their columns. Where a published metric fits a slot it uses that metric; otherwise it writes a query over these tables. Nothing is saved yet. You can let it work in the background and come back when it is ready.
  3. Configure. A line says how many slots HERC filled, and how many required slots still need a source. Name the dashboard and choose its domain.
  4. Bind the slots. Each slot HERC looked at carries a verdict:

    • Matched: the source fits the slot as it is. The line under it says why.
    • Inferred: HERC derived the source from the columns it found. The line says what it inferred, so you can check it.
    • Missing: HERC found nothing. Choose a source yourself, or Create a metric. The metric builder opens in a new tab; once the metric is published, pick it here. A required slot that is still missing keeps New Dashboard disabled.

    On a connection whose engine cannot run a metric query, such as PostgreSQL, HERC binds no metric. The slot reads Missing, or keeps the query HERC wrote. The bind step offers metrics disabled and says why.

    When HERC proposed something that was not kept (a comparison the source cannot draw, an action that stated figures), the slot says so. A query HERC wrote next to a published metric is only a note: the metric is used.

    HERC gives every signal its own format. Where its columns or title name a unit (avg_basket_eur, conversion_pct, NPS), that unit is used, even when HERC said otherwise. The slot then carries a note, Format corrected, and its Format field shows the unit used. Check it, and change it if the names were misleading.

    HERC leaves the choice of store to the dashboard filter, and writes each signal as one row per week or month, so its chart draws a trend. Each block adds up every store for the period, so with nothing picked in the filter (All) the dashboard shows the total, and picking one store shows that store's own figure. HERC is asked to weight a rate such as conversion (all transactions over all footfall) rather than average each store's rate, and, where the tables hold nothing to weight it by, to average the rate and mark the slot Inferred; Datahub does not check how a rate is weighted, so read a rate slot's note. Once the filter has a column, Datahub does check that each block adds up the stores: a query that still returns a row per store is sent back to HERC, and if it still does it is not kept, so the slot reads Missing and says why. A dashboard HERC filled before this check keeps its queries; if it shows one store's figure on All, change each block's query in the card editor to add up the stores per period (Ask HERC on the card can propose it), or create the dashboard again. If the filter column is not the one HERC wrote its queries for, the bind step says so under the filter column and offers HERC's column in one click (for example Use store_code); it also warns when HERC found no filter column. Until you take HERC's column, fill the slots again with yours, or replace HERC's queries, New Dashboard stays disabled.

    Datahub also checks three things that would show wrong figures, whether or not the filter has a column. A signal's trend must end at the latest week or month: a query that sorts the weeks oldest first and keeps the first twelve stops before the latest data, so it is sent back to HERC. A rate must divide two different figures: footfall over footfall reads 100% every week, whatever the stores did, so that query is sent back too. A column that already holds a percent, such as a conversion rate stored as 19.88, is shown as it is (19,88%): a query that multiplies it by 100 again shows 1988%, so it is sent back as well. Datahub tells such a column by its name, which says pct, percent, percentage or procent, or holds a "%"; a column named rate or ratio may hold a fraction from 0 to 1, where multiplying by 100 is right, so it is not checked. Nor is a percent column whose name says no unit (conversie, uptime): check that figure on the new dashboard. If HERC's corrected query still does any of these, it is not kept, and the slot reads Missing and says why. A dashboard HERC filled before this check keeps its queries: if a trend stops short of the latest week, a rate reads 100% every period or a percent reads 100 times too high, change the card's query in the card editor (Ask HERC on the card can propose it), or create the dashboard again.

    A comparison must be with another figure. When HERC compares a signal, the headline or a scorecard row with its own figure, such as a margin compared with the same margin column (or the same calculation under another name) and labelled t.o.v. netwerk-gemiddelde, the block would show no change every period, since its reference is the same figure. Datahub drops that comparison, and the slot says so. A signal needs a reference, so that signal reads Missing: pick Choose yourself on the slot and bind a source with its own reference column, such as a target, a plan or last period's figure. The headline or scorecard row keeps its figure, shown without a change, and a card label that named the dropped reference is replaced; it reads No comparison when no row compares any more. The same figure over another period, such as last week's margin, is a real comparison and is kept. A dashboard HERC filled before this check keeps its comparisons: if a signal or row shows no change every period, check its reference column in the card editor.

    On a scorecard, every change names what it is measured against:

    • The card's comparison label names the bases its rows really use, such as vs last year, or vs target and last year when the rows differ. In that case each row also names its own base. If HERC's label says something else, or only "vs previous" without saying which period, it is replaced, and the slot says so. The same goes for a row label HERC wrote that names another base than the row's column holds.
    • A row keeps its comparison only when its column, or HERC, says whether it is last year, the previous period, a target or a reference.
    • A reference is a figure to measure against that is not a goal, such as the chain average, a benchmark or the best store. A column named for one, such as nps_chain_avg, region_avg_basket or nps_benchmark, is read as a reference. A row compared with one says so in HERC's words, such as vs chain avg, or vs reference. It is never labelled vs target. Its change badge is coloured by the row's good direction, as on any row, never as a target hit or miss. On a card whose rows all compare with a reference, HERC's label is kept only when it names that reference; a label such as vs previous or vs last year is replaced, and the slot says so.
    • A forecast is read as a target, like a budget or a plan.
    • A comparison column whose name hides another figure is dropped, and the slot says so. An example is last year's revenue renamed "transactions last year".
    • Every row carries its good direction, so a falling returns rate shows green. When HERC gives a row none, a row named for something whose rise is bad news (shrinkage, returns, absence, costs, claims) counts as lower is better.
    • A percentage row shows as a percentage and changes in percentage points.
    • Change anything, then create. What HERC wrote shows the sentence, comparisons and suggested actions HERC proposed, marked AI suggestion. Changing a slot's title or fields keeps that label. Picking another source drops what HERC wrote for that slot, label and all. The dashboard is created exactly as the bind step shows it.

When HERC cannot help

If no language model is set up, or HERC times out or errors, the tables step says so and offers Bind the slots yourself: the same configure and bind steps, without HERC's proposal. Without access to the connection, it says so too: pick another connection or ask an admin for access.

Action-list dashboards

/insights/new → Action list — a fourth, single-purpose way to create a dashboard, alongside the three on-ramps above. An action list is a dashboard bound to one governed saved query: pick a query with a published (active) version up front, and the dashboard is created with exactly one locked table card showing that query's full result. Optional KPI cards can still be added on top.

The point is linking: an alert that runs the same saved query — pinned, or watching it as a governed query — can link to the action list from its message (the {{action_list_link}} placeholder), so a recipient has somewhere to click through to and act on the rows that triggered it, instead of only a table pasted into the notification. The alert builder can also create the action list in place.

flowchart LR
    A[Pick a saved query] --> B[Create action-list dashboard]
    B --> C[Table card auto-bound to query]
    C --> D[Alert links to dashboard]
    D:::accent
    classDef accent fill:#ff8400,stroke:#e67700,color:#fff

KPIs on top. In design mode an action list has an Add KPI button. It opens the card editor already bound to the list's own query and counting its rows, in a four-across row directly above the table — change the measure (a sum of amounts, a count of distinct vendors) or the title before you save. The first time an Insights manager opens an action list that is still only its table, it offers one ("Start with a headline number?" — Add KPI or Not now), however they got there, including from the alert builder's Open action list. Opened from an alert, the list is a side task of that alert: a bar under the header leads back to it, and saving a card here (a KPI, say) tells the alert you are done, so the bar's Return turns primary. Only the list the alert opened does that; a card saved on another list on the way does not. See Alerts: building out the action list.

Because the dashboard's whole identity is that one query, the editor won't let you add or retype a second table card here — the Table tile is disabled with an explanation when you're editing an action-list dashboard. Every other card type (metric, chart, matrix, multi-metric, map) can still be added freely. Renaming the table card itself, or changing its display settings, works as normal; only its data source is locked, and it can't be summarised — its rows are the list the alert links to.

A saved query with declared parameters ({{param}} placeholders with no default) can't back an action list — the table card has no way to collect a value for them at view time, so the picker shows it disabled with an explanation. Pick a query without parameters, or drop them from the query first.

Filters and parameters

  • Global filters at the dashboard level: date range, number, dropdown — auto-detected from the column type. Number filters carry a comparison operator (=, ≠, >, ≥, <, ≤) the viewer can change at runtime. Building one no longer requires a connected warehouse: the column picker also offers every column already used by the dashboard's own cards, so a dashboard built entirely on Data Catalog assets still gets a real, working global filter.
  • Card filters per card apply to that card only — use a global filter instead when you want a filter to affect every card on the dashboard.
  • Catalog-backed dropdowns — a card bound to a Data Asset loads its filter options from the active dataset version (the same records the card queries). You only need Insights view permission; catalog edit permission is not required. On a map or table, every value already plotted stays in the dropdown even when the asset has more than 100 distinct values. Adding a filter, or activating a new dataset version, refreshes the lists. If one filter column was removed from the asset, the other dropdowns on the card still load.
  • Filter pills are the whole picture — both card and dashboard filters render as pills you can change directly on the card/dashboard, so there's nothing extra to open to see what's applied. A card with more than two filters keeps the ones with a value in its header and the others in its view options. Once you pick a value in a dashboard filter that can't reach a particular card (its column isn't on that card's data, or a card-level filter of the same name takes over), the card says Not filtered by that filter above its numbers, with the reason. A chart click that filters the other cards is named the same way on a card it can't reach.
  • Cross-filter cascading — picking a value in one filter narrows a sibling filter's dropdown to only the values that still occur together with your selection, the same way it narrows the cards' results. A filter never narrows its own list. A filter whose options come from a connected warehouse query can narrow its siblings, but its own dropdown isn't narrowed by them.
  • Multi-page — pages share global filters; switching pages doesn't reset them.
  • Defaults — in design mode, each report filter's Default is what every card starts on until a viewer changes it. A Multiple values filter can have several defaults. The default is applied by the platform itself, so every card — and every other way of opening the dashboard — runs with it, not just the filter bar.
  • Sort values by — a Single value or Multiple values filter can list its dropdown in the order of another column of its own source instead of by the value itself, ascending or descending: month names by month number, for example. A filter on a connection gets its generated options query rewritten in that order; a hand-written options query keeps its own ORDER BY, and the filter card says so. A catalog card's or a model field's values are put in that order by the platform. When a filter reads several catalog assets, the first asset's order leads. On a published report, a catalog or model filter's dropdown shows its new order once the draft is published.
  • Select all / Deselect all — once every listed value is picked, a picker's Select all row reads Deselect all and clears the picks. In Restrict selectable values it only does so when something would stay allowed, because an empty allow-list means no restriction.
  • Restricted values — a Single value or Multiple values filter can be limited to a set of allowed values (Restrict selectable values). Viewers can only pick from that set, and with nothing picked the cards run on the whole allowed set — the pill reads All allowed, never "All". Clearing the filter goes back to the allowed set, not to all data. Without a restriction, clearing a filter means all data.
  • Ranges — a Number, Date or Date range filter can be limited to a Minimum, a Maximum or both. The cards only show rows inside the range, whatever the viewer picks. A Number or Date range pill states the range and doesn't offer a value outside it: a number outside it can't be confirmed, a date preset whose dates fall outside it today is greyed out, and a custom date outside it can't be applied. A Date filter's calendar greys out the days outside it.
  • A value outside the limit is refused, not trimmed — if a filter holds a value outside its allowed values or its range, the cards that filter reaches say which value is outside the limit and what is allowed. The pill gets a warning button that clears the filter. Cards the filter doesn't reach are not affected. For a range, every value counts: both ends of a between, both ends of a date range, and each value of an in list. A ≠ value is the exception: the range never cuts it short, so it isn't checked. So "2018 - 2022" under a minimum of 2020 is refused rather than shown as 2020-2022. An open end is not a value. Such a value typically comes from a saved view made before the restriction was added or changed, or from a date typed into a Date filter outside its range. A preset is named as you picked it (Last 30 days), and dates are shown in your date format. A default outside the limit is not applied: the cards run on the allowed set, or the range, alone. Changing the range never deletes a default. In design mode, the Default field says when its value is outside the range; for a date preset, that depends on today's date.
  • Save my view / Reset my view — a viewer can save their current filter choices as their personal view; it opens with those choices next time. When a saved view holds a value a filter no longer allows, the page says so: clearing the filter fixes that visit only. Save my view there saves your view without the refused value (or reset it to the dashboard's own defaults) to fix it for good.
  • Card filter vs. dashboard filter of the same name — the card's own filter takes over on that card: the card runs with what its own pill shows, and the dashboard's value (and default) for that name doesn't reach it. A dashboard restriction on that column still applies unless the card filter has a restriction of its own. When the two filters are of the same kind, the card's pill shows it: it states the dashboard's range, offers only its allowed values, and doesn't show a card default outside it as applied.
  • Restrictions on cards with their own SQL. A filter narrows a SQL card whose query uses its column, including a query that takes its top rows, ranks them or totals them: the filter applies first, on every warehouse, Azure SQL and Fabric included. Some queries can't take a filter safely: two joined tables both have the column, or, on Azure SQL and Fabric, a CTE or subquery before the main query also uses it. There, an ordinary filter is marked as not applying to that card, and a restricted filter withholds the card with a message naming the filter, because the card would show rows outside the restriction. Someone who can edit the card is told what to change in the query. Three cases are not covered yet, and those cards can show rows outside the restriction: a query that uses SELECT * without naming the column; on Databricks and PostgreSQL, a column the query computes itself (for example year(order_date) AS year); and a query that combines parts (a UNION, or a join on the column) where the restriction reaches one part but not another.
  • Alerts from a card keep its filters. Create alert on a card starts an alert on the card's query with the filters the card is showing written into it: your picks, the dashboard's defaults, and its restrictions. The alert keeps those values; changing the dashboard's filters later doesn't change the alert. A date filter is written in as the dates it means that day, so a "Last 30 days" stays on those 30 days; the alert builder says so, and you can change it in the query to a relative date. An alert on a metric or a saved query can't carry the filters, and the alert builder names the ones it leaves out. A card that asks a semantic model a question makes an alert on that question, with the filters written into it; when the card shows several measures you choose the one to watch (see Watching a semantic model).

Filters are bound through SQL parameters ({{name}}), and the platform's parameter expander handles the operator + value pair safely — no string interpolation into SQL.

In the card editor, Filter Placeholders under the SQL lists the dashboard's and the card's filters. Click in the SQL where a filter's value goes (for example after WHERE year =), then click the filter: its {{name}} goes in at the cursor, or at the end of the SQL when you have not clicked into it yet or the cursor is in a comment. Click a filter that is already in the SQL to take it out. Refresh in the editor runs the card with each filter's default; on the dashboard it runs with the value picked there, or the default. A placeholder whose filter has neither stays unfilled and the card fails; on Databricks the message names the placeholder. The editor names such a placeholder under the filters, so give its filter a default value. A long query scrolls inside the editor; Show all SQL shows it whole.

Filters on a semantic model's fields

A report can use a semantic model of its connection. A page filter on one of the model's fields then reaches every card the model's relationships connect to that field's table, not only the cards whose query has a column of that name. For example, a filter on the customer's Region also narrows a card built only on orders, because the model says how orders join to customers.

  1. Choose the model. In design mode, open the report's Settings and pick a Semantic model. The list offers the published models on the report's connection that you may read. Open model takes you to the model's page. Choosing a model is a change to the report like any other.
  2. Add a filter from the model's fields. With a model chosen, the filter editor offers Add filter from the model's fields instead of the connection's columns. Fields are grouped by table under their labels. Search finds a field by its label, its column name or a synonym. Hidden fields are not offered, and a field that already has a filter can't be picked twice. The new filter is named after the field's label; rename it if you like. The row says which model field it reads.
  3. Pick values. The filter's dropdown lists the field's values from the warehouse, read as you. If they can't be listed, the dropdown says why, for example that the warehouse is starting, that reading the values takes too long, or that you have no access to the connection.
  4. See where it applies. Once a value is picked, a card the filter can't reach says Not filtered by that filter above its numbers, with the reason: the card uses another connection, it doesn't read a table the model links to the field's table, it reads the field's table only to leave rows out (NOT IN, NOT EXISTS, <> ALL or the right side of EXCEPT), or the field was removed from the model. A card of the third kind is left unfiltered on purpose: a filter there would make the left-out set smaller, so the card would show more rows instead of fewer. Two join forms leave rows out the same way and are left unfiltered too: the right side of a LEFT ANTI JOIN, and a LEFT JOIN whose WHERE checks a column of the joined table with IS NULL, as in WHERE c.customer_id IS NULL or a soft-delete check such as WHERE c.deleted_at IS NULL. With IS NULL, a row the filter leaves out of that table comes back as unmatched. For these the card gives the same reason. The right side of a LEFT SEMI JOIN keeps rows rather than leaving them out, so a filter there narrows the joined table inside the join. A filter with no value picked narrows no card, so no card mentions it.

On Azure SQL and Fabric, a field filter is added to a SQL card's query as written: its TOP, ORDER BY, CTEs, hints and functions such as SYSDATETIME() stay exactly as they are. A query that ends in FOR JSON or FOR XML, reads a temporal table with FOR SYSTEM_TIME, or holds more than one statement can't take the filter. That card says the filter is not applied because its query couldn't be read, and a filter with allowed values withholds it. Name the model's tables in full in these queries, as database.schema.table: a schema.table name may not be matched to the model's table, and the card then says the table is named without its catalog or schema. Metric cards on Fabric don't take field filters yet, and clicking a chart on an Azure SQL or Fabric card doesn't filter the other cards yet.

Changing the model checks your field filters first. If the new model has no field for some of them, the report names those filters and asks you to confirm; they filter no card until you pick a field for them again. Removing the model also asks first: the field filters then match cards by column name, like any filter on a report without a model.

Some model changes are refused. When that happens the report keeps the model it had, and Settings says why under the picker:

  • The report holds cards that don't read a model. A report on a model holds model cards, text, platform statistics, and metrics on the model's tables only. Settings lists each other card by title and page. Open card takes you to it: archive it with the archive button on the card, then pick the model again. The list counts down as the cards go.
  • The connection is not Databricks or Microsoft Fabric. Model cards run on those two only, so the report can't use a semantic model. Leave it without one; its cards keep running on the connection.
  • Model cards are still on the report. Removing the model or choosing another one is refused while cards that ask this model for their measures remain. Settings lists them the same way. Archive them first, then make the change again.

Filter names starting with dh_mf_ are reserved for these filters, and the filter editor asks for another name. A report without a model works exactly as before.

Edit-in-place vs full editor

  • Inline edit: from the viewer, click Edit → cards get hover overlays (pencil + archive). Click the pencil → the right-hand panel opens the card edit form. The dashboard stays visible; you can click another card to edit it without leaving.
  • Add charts: in inline edit mode, an empty slot appears for any archived card; click Add charts to browse archived cards in a 3-column grid and batch-restore.
  • Full editor: click the gear → /insights/{id}/edit for page management, layout picker, and dashboard settings.

Inline edit is the day-to-day flow; the full editor is for restructuring.

On a report with a semantic model. The report holds only the cards its model runs, and that goes for cards brought back too:

  • Add charts lists every archived card. One the model can't run is greyed out, with the reason under it. A restore that is still refused says why in the dialog, and the rest of your picks stay picked.
  • Restoring an archived section or page brings back the cards the model runs. The others stay archived, and a notice names them.
  • A model card on a report without a model can't be restored. Pick the model in Settings first.
  • The metric picker in a metric card's editor lists only the metrics that read the model's tables, and says so. If the card's own metric isn't one of them, the picker says that too: the metric stays listed for this card, and you pick one on the model to replace it.

AI assistance

  • AI dashboard generation (/insights/new → AI tab). Describe the dashboard; the insights agent reads the connection's published metrics first, then any SQL it needs to invent. The generator validates every generated query (column allowlist + EXPLAIN + an actual LIMIT 1 execution) and includes auto-corrected fallbacks.
  • Draft from a semantic model. On a SQL warehouse, the tables step offers a Semantic model. The list holds the published models on the connection that you may read. HERC then drafts from the model's tables, joins and fields. The new report uses that model, and its page filters keep their model fields. The preview shows each filter's model field, or Not in the model for a filter that matches cards by column name.
    • Apply changes, under Refine with HERC, changes the draft in place and keeps the model. Discuss with HERC talks the draft through in the chat instead.
    • If HERC can't use the model, the step says why. For a model without a published version, the step links to the model so you can publish it and Try again. Continue without a model drafts or creates the dashboard without one.
    • The same check runs when you create the dashboard. A model archived since you drafted is caught before anything is created.
  • Fix with HERC from a card's error. A SQL card that fails shows Fix with HERC next to its error, to anyone who may edit the card: the same people who see Edit this card. Clicking it opens the card's editor and sends HERC one chat message that names the card and the error you saw. On a report that uses a semantic model, the message asks HERC to keep the fix to that model's tables and joins. HERC proposes the SQL; you read it, Apply it into the editor and save. Nothing changes until you do. If the editor has unsaved changes for another card, you are asked first, and cancelling sends nothing.
    • The button is not offered for an error the SQL can't fix: a filter value or limit the report refuses, a warehouse that rejects the connection's credentials or refuses the connection, a Databricks connection still waiting for your consent, and a warehouse or query that is still starting. Edit this card stays.
  • Ask HERC from a card. Click Ask HERC in the card editor: HERC gets the card's SQL, columns and any error. It can run discovery queries and change the display config, metric binding, title and type directly. SQL it proposes for you to read and Apply into the editor; nothing is saved until you save. See How HERC edits SQL. If HERC changes the card while you have unsaved edits, the editor keeps your edits and offers to load the latest version instead of overwriting either.
  • Metric cards show one value. A single-value metric card shows the first row of the result, in the value column, or in the first column when no value column is set or it is not in the result. The card editor says which cell that is and warns when the query returns several rows or falls back to the first column. Put the value first and return one row.

Metrics-first is a hard rule

If a published metric already covers the brief, the generator binds the card with metric_ref rather than reinventing the SQL. Ad-hoc SQL only fills the gaps a metric doesn't cover — so a dashboard inherits governed definitions wherever they exist.

Query execution & caching

SQL-backed cards are cached in Postgres after each successful run so a filter change or a page switch doesn't re-hit Databricks for every viewer. The cache key captures the rendered SQL, the parameter values, the connection, and — under per-user OAuth — the caller, so nothing is ever served across identities.

sequenceDiagram
    autonumber
    participant V as Viewer
    participant DH as Datahub
    participant PG as Result cache
    participant DBX as Databricks SQL
    V->>DH: Open dashboard / change filter / Refresh
    DH->>DH: Build cache key<br/>rendered SQL · params · connection · caller
    alt fresh cache hit
        DH->>PG: Read cached rows
        PG-->>DH: Rows
    else miss or Refresh (bypass)
        DH->>DH: Validate read-only (block DDL / DML)
        DH->>DBX: Run statement
        DBX-->>DH: Rows (a warehouse still starting: asks again after about 50 s)
        DH->>PG: Store with resolved TTL
    end
    DH-->>V: Render card

Figure 2 — SQL-backed card execution. A fresh cache hit skips Databricks entirely; a miss (or a *Refresh*) validates the SQL, runs it live, then caches the result under its resolved TTL. On a warehouse that is still starting, each run answers after about 50 seconds and the card tries again by itself until the warehouse is up.

Per-user identity, per-user cache

Under Databricks per-user OAuth the cache key includes the calling user, so row-level security is preserved end to end — one viewer's rows are never served to another. With a service-principal or PAT connection the caller component is dropped and the cache is shared across the whole organisation, which is the intended behaviour there.

Each SQL card's result is reused until it expires. The time-to-live cascades: a per-card override wins, else the per-connection default, else 24 hours. Refresh any card on demand from its Refresh chip; admins see installation-wide cache stats and a purge-all button at /admin/insights-cache. Metric-backed cards ride the Metrics module's own cache under the same key contract. Full mechanics: Cached query results.

The dashboard header shows an "Updated <time ago>" badge — the oldest cached result among the cards on the page, i.e. how stale the thing you're looking at could be; hover it for the exact time. Dashboard managers (insights.manage) see a refresh icon next to it that purges the cache for every card on the dashboard, rather than waiting for it to expire on its own. The page you're currently viewing re-runs immediately; any other page picks up the fresh data the next time you open it.

Saved queries

A saved query is warehouse SQL with a name, stored once so that flows can run it. You save one from a flow's Capability step: choose Warehouse query, then Save new query. Data Catalog → Saved queries in the sidebar (/data-catalog/queries) lists the saved queries you can see. A dashboard card can show one too — see From Saved Query under Ways to back a card.

Tab What it lists
Mine The queries you own, private or shared. Domain stewards can see your private queries too, SQL included: the stewards of the domain a query is filed in, or any steward while it is not filed. While a version is under review, anyone who may approve saved queries can open it from the review task, SQL included, but never your drafts.
Shared with the organization Queries their owners have shared, so that others can use them in their flows.
Private to other owners For domain stewards who can manage Insights, and only while it holds something: other owners' private queries that are not filed yet, or that are filed in a domain you steward.
All Every query in the lists above, each once.

The list you pick stays picked when you open a query and come back. It is part of the page address, so a link to the page opens the same list.

Above the list, a row of counts covers every saved query you can see, each counted once: the total, how many are Active, Not reviewed, Changes not submitted and Not active yet (the words the Review status column uses, and together they make up the total), and how many are Not filed in a domain. Only a query's owner sees its unsubmitted changes, so Changes not submitted is shown to people who can create saved queries, and to anyone who already owns one with changes not yet submitted. Click a count to list exactly those queries under All. Any search or other filter is cleared first, so the list matches the number. On a domain's list the counts cover that domain only, and there is no Not filed count, since every query there is filed. The gap link on the Domains page opens the same list as the Not filed count. If a list does not load, the page says so and offers Try again.

Sharing and filing are separate columns. Sharing decides who may use a query in a flow. The governing domain names who is accountable for it. The Not filed filter on the domain column shows what is still waiting for a domain, and a domain's detail page links to the list of queries filed in that domain.

Filing a query in a domain

A query's domain can be set in two ways.

  • By its owner. Open the row's menu and choose File in a domain, or Change domain for a query that already has one. You can file your own query only into a domain you work in, and you can move it out of a domain only while you still work in that domain.
  • By a domain steward. A steward can file a query that someone else owns, as long as they steward every domain the change touches: the domain the query is in now, if it has one, and the domain it moves to, if the change sets one. The owner must also work in the domain it moves to, so that they can keep editing their own query. If they do not, the filing is refused, and the message says what to do. The domain is the only thing a steward can change. The name, the SQL, sharing, archiving and deleting stay with the owner.

When a steward files, moves or unfiles your query, you get a notification that names the steward and the domain. The change also appears in the audit log at /admin/audit-log as Domain changed, with the query's name, the domains it moved between, whether its owner or a domain steward moved it, who that was and when.

Seeing a query is not using it

A steward can see other owners' private queries so that someone can file them. That does not let the steward use such a query: a private query runs only in its owner's flows, until its owner shares it.

The same goes for reviewers. While a private query has a version under review, anyone who may approve saved queries can open it: the version under review and the active version it would replace, and they can run the version under review. The review may have fallen back to someone outside the query's domain. Older versions and drafts stay private, and when the review ends the whole query is private to its owner and its domain's stewards again. Every such read is recorded in the audit log at /admin/audit-log as Read a private query under review, with who read it, which version was under review and how often they opened it. The dialog that sends a private query to review tells its owner, before they send it, who will be able to read it.

Making a saved query runnable

A newly created saved query starts as a private draft — flows that reference it cannot run until its first version goes live. From the row's menu on /insights/queries, its owner can:

  • Submit for review — sends the draft to a reviewer. Flows keep running the query's current active version, if it has one, until the draft is approved.
  • Activate — puts the draft live immediately, with no review. Refused if your organization requires a review for saved queries.
  • Withdraw — cancels a review in flight and returns its version to draft.
stateDiagram-v2
    direction LR
    [*] --> Draft: Create
    Draft --> UnderReview: Submit for review
    UnderReview --> Active: Approve
    UnderReview --> Draft: Withdraw / Reject
    Draft --> Active: Activate (if review not required)
    classDef accent fill:#ff8400,stroke:#e67700,color:#fff
    class Active accent

Figure — A saved query's version chain. Submit and Activate are owner-only; both are disabled on a query filed in a domain its owner no longer works in.

Not offered on someone else's query

Submit, Activate and Withdraw only appear on your own rows — unlike filing, a domain steward cannot move another owner's query through review on their behalf.

Reviewing a saved query. The review task's View entity opens the query at the version under review. You see its SQL, and Run runs that version, so you can check what it returns before you approve. Only its owner and saved-query approvers can see a version under review. If a link points to a version you can't open (for example, one whose review was withdrawn or rejected since, which makes it a draft again), the page says so, and shows the version you can see instead.

Ask HERC while writing a saved query

The saved-query editor (new queries, and existing ones in edit mode) has an Ask HERC button. HERC proposes SQL, checked against the query's own connection, that you read and Apply; saving still creates a version that goes to review.

Review lifecycle

If a workflow is configured for insight_dashboard, a dashboard passes through a review gate before it becomes the canonical version of a report.

stateDiagram-v2
    direction LR
    [*] --> Draft: Create
    Draft --> UnderReview: Submit for review
    UnderReview --> Approved: Approve
    UnderReview --> Draft: Reject
    Draft --> Archived: Archive
    Approved --> Archived: Archive
    Archived --> Draft: Restore
    Archived --> [*]: Permanent delete
    classDef accent fill:#ff8400,stroke:#e67700,color:#ffffff,font-weight:600;
    class Approved accent

Figure 3 — A dashboard's lifecycle. It ships as a draft, optionally passes a review gate to become the canonical *Approved* version, and archive-before-delete keeps an archived copy restorable until a steward permanently removes it.

  • Click Submit for review on the dashboard. The window shows who reviews the draft. When nobody on the reviewing role other than you may approve it, you choose a reviewing group, never a single person, and the task lands in that group's team inbox in Tasks. Only groups with someone other than you who holds insights.approve are offered.
  • The reviewer approves or rejects; the dashboard's status moves accordingly. The viewer page shows the workflow progress timeline.
  • An approved dashboard can be referenced as the canonical version of that report.
  • If the dashboard is filed in a governing domain, archiving, restoring and permanently deleting it need membership of that domain, the same check an edit makes. A manager outside the domain is refused, and the message names the domain and says to ask a domain administrator to add their role group.

Export and import

  • Export (/insights/{id} → toolbar) downloads a portable JSON envelope with name, description, layout, cards, filters, and tag metadata. Tenant-local IDs (integration, governance, metric definition) are intentionally dropped.
  • Import (/insights → import) requires a destination integration; the platform creates a fresh dashboard with an (imported) suffix. A card whose source didn't come along (a metric, a saved query, a semantic model the import didn't keep, or a catalog table) becomes a SQL card that names its old source: open it in Design mode and pick a source in this environment. Platform statistics and text cards come along as themselves. When cards need a new source, or couldn't be imported because the file describes them wrongly, a notice says how many.
  • Importing a report with a semantic model. The import keeps the model when the destination connection may use it, as Settings would allow; otherwise it leaves the model off, and the audit log records why. With the model kept, metric cards stay metric cards and the model's own cards stay model cards. If the file holds cards the model can't run, the import is refused, and the dialog names them.

Grouped table cards

A table card can nest its rows under group rows. Under Group rows on the card editor's Build tab, add up to three columns, outermost first, and drag them to reorder. Each group row shows the column's value and how many rows it holds. It never shows a total: the table does not know whether a column can be added up, and a summed percentage or average is a misleading number. For totals, use a matrix card.

  • The grouped columns leave the header. A leading header names them (Region › Country); click it to sort the groups A→Z, Z→A, or back to the order the query returned them in.
  • Sorting another column orders the rows inside each group. The groups stay where they are.
  • Filters apply first. A group whose rows are all filtered out disappears, and every count is a filtered count.
  • Rows with no value in a grouped column collect in one (empty) group, listed last when the groups are sorted.
  • Paging counts what you can see. A closed group is one row on a page, however many rows it holds. A page that starts inside a group repeats that group's row (and the ones above it) at the top, marked (continued), so its rows are never shown without their group. The repeat is not counted in the page's "Showing" range.
  • A column filter on a grouped column is set aside while the column is grouped: it has no header left to show or clear the filter from. Ungroup the column and the filter is back.
  • The editor names a grouped column the card cannot use — one the query no longer returns, or one that would leave the rows no visible column of their own.

The level buttons and the Default level setting work as they do on a matrix, with one more level: the last one shows the rows themselves. A table grouped by one column has 1 (just the groups) and All.

Pivot matrix cards

A matrix card turns flat query rows into a cross-tab: rows grouped one way, columns grouped another, and an aggregated number where they meet. The rows, columns, measures, totals, values and order below are on the card editor's Build tab; the Appearance settings are on its Format tab.

Rows, columns and measures

Three ordered lists, each drag-reorderable:

  • Rows — one or more columns to group by. A second dimension nests inside the first, and each group gets an expand/collapse chevron and its own subtotal line.
  • Columns — optional. Each dimension adds a level to the column header. Leave it empty and the measures fill a single column.
  • Measures — the number in each cell. Each measure picks an aggregation (sum, average, minimum, maximum, count of rows, distinct count, median) and a column, and can carry its own label, number format and percent mode. Add more than one and every column slot repeats for each.

Only distinct count is offered over a text column — the arithmetic aggregations list numeric columns only, because summing text produces an empty grid. If a measure ends up with no value anywhere, the card says so and names the column rather than showing a blank grid with totals under it.

flowchart LR
    A[Query rows] --> B[Group by row & column dimensions]
    B --> C[Aggregate each measure per cell]
    C --> D{Show values as}
    D -->|raw| E[Cell]
    D -->|% of row / column / total| F[Divide by the rendered denominator]
    F --> E
    classDef accent fill:#ff8400,stroke:#e67700,color:#fff
    class C accent

Totals and subtotals

A grand-total row, a grand-total column, subtotals on each row group, and a subtotal column per column group — each toggled independently. Subtotal options only appear once there is a nested level for them to summarise.

Totals are recalculated, not added up

A subtotal is computed from the underlying rows, not by adding the cells above it. This matters for every aggregation that is not a sum: the average of a region is the average of its rows, not the average of its products' averages, and a distinct count of customers across four quarters counts each customer once.

Show values as

Raw value, % of row, % of column, or % of grand total — card-wide, or per measure so you can put a figure and its share side by side. Percentages are always taken against the detail cells of the grid as displayed, so a total reads 100% even when a top-N limit is hiding groups. The card header names the base, so a cell reading 31,3% always says what it is 31,3% of.

Order and limits

Each axis's order and limit sit in its Rows or Columns section on the card editor's Build tab. Sort each axis by label (A→Z or Z→A), by value (largest or smallest first), or leave it in the order the query returned. Clicking a column header re-sorts the rows by that column for you only — it never changes what the dashboard saves.

Limit rows / Limit columns keep the first N outermost groups in that order. A kept group keeps all of its detail, so with Value, largest first "top 10 products" means ten whole products, not the ten biggest individual rows. Under a label order the limit keeps the first N names instead; the section says so and offers Show the largest, which sorts the axis largest first. Value orders and Show the largest go by the first measure. The Total row and column add up only the groups the limit keeps. A note under the card says how many groups were kept out of how many.

Appearance

Setting What it does
Numeric / Heatmap / Data bars Plain figures, a colour wash, or an in-cell bar.
Colour scale Brand, info, cool, warm, or success-danger. The last is diverging: it splits at zero when values cross zero, and at the midpoint when they do not.
Colour scale covers / Bar length compares The whole matrix, each row, or each column — use per row or per column to compare within a line rather than across the grid. The label follows the display mode.
Row height Compact or comfortable.
Keep headers visible Column headers and the row-label column stay put while you scroll. A matrix (or table) wider than its card fades at the edge that has columns out of view, so you can tell there is more to scroll to.
Let viewers collapse row groups Shows the expand/collapse chevrons and the level buttons.
Default level How far the row groups are open when the card loads, named by the dimension it stops at (1 — Region). All levels by default. Offered only while row groups can collapse.
Empty cell shows What to print where a combination has no rows. Blank by default.

Grand totals, and the subtotal line of an open group, are never tinted or barred — they are an order of magnitude larger than the cells they summarise, so colouring them would flatten everything else to the pale end of the scale. A closed group keeps its colour or bar: it is compared with the other groups at its own level, not with the rows it hides.

Thin lines separate the groups, at every level: between years, and between the months inside each year. Pick a heavier line, or none, under Lines.

Reading the legend. A heatmap or data-bar matrix shows a key under the grid. A heatmap shows its colour ramp, labelled with the real lowest and highest values when one scale covers the whole matrix, or Low / High when each row, column or measure has its own scale. The caption says what the colour (or bar length) compares across, whether each measure has its own scale, and that totals are left out. Bars are measured from zero: an all-negative column grows leftwards. When a row (or column, or the whole matrix) holds both positive and negative values, its bars grow either way from a centre line; a row whose values all share a sign has no centre line and its bars start at the edge. The bars legend shows the colour of a positive and a negative bar (they differ only on the success-danger scale) and the value the longest bar stands for, so you can read every other bar against it. When nothing can be drawn — every value equal in a heatmap, every value zero in bars — the legend says so instead of showing a scale.

Heatmap colours and bars follow light and dark mode. Each colour scale is tuned so its strongest cell is equally strong in both, and the text on it stays easy to read.

Totals over a truncated result

The pivot is computed in your browser from the rows the query returned, and queries are capped at 10,000 rows. When a result is truncated, the card asks your warehouse to group every row the query returns, so each cell, subtotal, grand total and percentage is exact, and groups beyond the cut still appear.

The card falls back to the rows it has, under a warning that its totals are partial, when exact totals cannot be fetched: on an Azure SQL or Fabric connection, on a card backed by a metric or bound to a Data Asset, on a card with analytics, when a sum, average, minimum, maximum or median reads a text column, for a median or distinct count whose Limit rows / Limit columns setting hides groups, or when grouping every row takes the warehouse longer than 15 seconds. Narrow the query, or aggregate in SQL and pivot the smaller result.

KPI cards over a truncated result

A Bars KPI shows the last row it read as the current value. A Sparkline KPI shows the period you picked, or, with nothing picked, the last row it read. When the result was truncated, that row may not be the latest one, so the card says so under the value. A result so large that not even its first row came back shows a notice saying so, not "No data", on every card type: there is data, too much of it. Narrow the query, select fewer columns, or aggregate it in SQL.

Opening row groups to a level

A matrix with two or more row dimensions shows level buttons in its header: 1 shows only the outermost groups, 2 opens them one step, and All opens everything. A closed group keeps its subtotal on its own line, even with row subtotals turned off, so level 1 reads as a summary of the top groups. A measure's Groups show setting picks what that line shows. There is no button for the last dimension: opening it shows exactly what All shows.

The buttons and the chevrons work together. Pick a level, then open one group with its chevron: no button stays pressed, because the view no longer matches a level, and picking a level again resets every chevron. What a viewer opens is theirs alone and is not saved; the card opens at its Default level every time it loads.

Matrix cards built before this

An existing matrix keeps its data and its settings — its single row, column and value fields are read as a one-row, one-column, one-measure pivot, and every new capability starts off. Two things do change: values are right-aligned with rules between column groups, and a category whose value is not a number now appears with empty cells instead of vanishing from the grid entirely.

Limitations

Limit Why Workaround
Queries are read-only — DDL / DML are blocked. Safety. Wire writes via Flows triggered by an Alerts rule.
Cold SQL warehouses can take 1–3 minutes to warm (occasionally 5–7). Databricks behaviour. Each run waits about 50 seconds. A card then shows "Warehouse is starting up" and tries again by itself, for about twenty minutes, and loads once the warehouse is up. Run in the query editor or on a saved query says to try again in a minute. Use a serverless warehouse to avoid cold starts.
Metric-backed cards can't preview SQL in the modal. The metric's compiled SQL is server-only. The card runs immediately on save; the dashboard refreshes.
A story template slot cannot bind a published metric on a connection whose engine runs no metric query (PostgreSQL, Azure SQL). Metric queries run on Databricks and Microsoft Fabric only. Bind the slot to a saved query, or let HERC write SQL for it.
Export drops governance metadata (domain, department, team) and tenant-specific IDs. Tenant boundary. Re-tag in the destination.
A matrix pivots in the browser, over at most 10,000 returned rows. The pivot is client-side, so it can only see what the query returned. On Databricks and PostgreSQL, a SQL or saved-query card fetches exact totals from the warehouse when a result is truncated (see Appearance). Elsewhere, aggregate in SQL and pivot the smaller result; the card warns when its totals are partial.
Embedded view doesn't honour OAuth U2M for embedded Lakeview dashboards. The embedding identity is per-organisation. For per-user RLS, view the dashboard in the Dashboards module; for ad-hoc, build it in Insights with U2M.

Audit & compliance

Question a CISO might ask Where to look
"Whose Databricks identity ran this query?" OAuth U2M: the calling user's. PAT / SP: the integration's identity. The cache key reflects this.
"Did this dashboard run a write?" The read-only validator blocks DDL / DML before execution; the response logs the actual SQL.
"Who approved this dashboard?" Workflow progress card on the viewer; full audit at /admin/audit-log filtered by module insights and entity type dashboard.
"Who exported this dashboard?" /admin/audit-log filtered by module insights, entity type dashboard, action exported. Every export records the actor and timestamp.
"Where did this exported dashboard end up?" Export is a download — the recipient is whoever you sent the file to. The platform records who triggered the export but not the download destination.
"Can a non-author edit a dashboard?" insights.manage is required for any mutation. If the dashboard is filed in a governing domain, the editor must also be a member of that domain.
"Can a manager archive, restore or delete a dashboard outside their domain?" No. For a dashboard filed in a governing domain, archive, restore and permanent delete need the same domain membership as an edit, and the refusal names the domain. A dashboard not filed in any domain stays open to every insights.manage holder.
"Who moved this saved query to another domain?" /admin/audit-log filtered by module insights, entity type warehouse_query, action domain_changed: each row names the query, the domains it moved between, whether its owner or a domain steward moved it, and who that was. When it was a steward, the owner also received a notification that names the domain.

Troubleshooting

Symptom Likely cause Fix
Card shows "Warehouse is starting up" Warehouse cold-starting. Nothing to do: the card tries again by itself and loads once the warehouse is up, usually within a few minutes. If it then says to try again in a minute, reload the dashboard; switch to a serverless warehouse to avoid the wait.
Run in the query editor, or on a saved query, says "The Databricks warehouse is starting up. Try again in a minute" The connection's Databricks SQL warehouse had stopped. Run waits about 50 seconds, then says so instead of waiting on. The query it sent is stopped, so it does not run later. Run it again after a minute. A stopped warehouse can take a few minutes to start.
A card or Run says "This query is taking longer than expected" The warehouse is running, and the query itself is slow. It is left to finish. A card tries again by itself. For Run, run it again in a moment, or narrow the query with a filter or aggregate it in SQL.
The guided query editor, the AI dashboard brief's table picker, or a dashboard's default catalog and schema settings say "The warehouse is starting" The connection's Databricks SQL warehouse had stopped. The pickers wait about 30 seconds, then say so instead of waiting on. Click Try again after a minute; it asks again only for the lists that were waiting. A stopped warehouse can take a few minutes to start.
The guided query editor says "The warehouse did not answer" No answer arrived in time. The warehouse may still be starting, or the connection is slow. Click Try again after a minute. If it keeps happening while the warehouse is running, run Test connection on the integration.
A picker says "Couldn't load this list: … was not found on this connection, or you do not have access to it" The catalog, schema or table no longer exists, or the connection's identity cannot read it. Pick another name, or ask the warehouse owner for access.
The Semantic model list is empty No model on the report's connection has a published version, or you don't hold semanticmodel.read. Publish a version of the model, or ask an administrator for the role.
Choosing a model is refused The message gives the reason: the model was archived, it has no published version yet, it describes another connection, or you can't read it. Restore or publish the model, or pick one on the report's connection.
A card says Not filtered by a model filter The card uses another connection, doesn't read a table the model links to the field's table, reads the field's table only to leave rows out (NOT IN, NOT EXISTS, <> ALL, EXCEPT, LEFT ANTI JOIN, or LEFT JOIN … WHERE … IS NULL), or the field was removed from the model. Add the missing relationship to the model, pick another field, or leave the card unfiltered on purpose. For a card that only leaves rows out, filter the rows the card shows instead, for example by joining the field's table in the card's main query.
Card returns "0 rows" but you expected data The query genuinely returned no rows; or a filter wiped them. Check the active filter pills on the card (including those in its view options) and dashboard, and any Not filtered by note above the card's numbers; check the Total rows badge in Insights logs.
"Column not found" from an AI-generated card The model hallucinated a column. Open the card's Ask AI panel; the agent auto-discovers the actual columns and rewrites.
412 DATABRICKS_OAUTH_CONSENT_REQUIRED OAuth U2M consent missing. The card prompts you to re-consent.
424 WAREHOUSE_CREDENTIALS_REJECTED The warehouse credential (Databricks PAT, OAuth client secret) was rejected or has expired. Rotate the credential on the integration's connection settings, then run Test connection and retry. You stay signed in to DataHub — only the warehouse call failed.
Metric tab in Add Card is empty No active, published metrics for this dashboard's connection. Publish a metric for the same connection; refresh.
409 METRIC_INTEGRATION_MISMATCH on save The metric is on a different connection than the dashboard. Pick a different metric or change the dashboard's connection.
Submitted-for-review status stuck Workflow misconfigured (no reviewer in the role group). Add members to the role group, or cancel and re-submit.
Change domain is disabled on a saved query someone else owns You steward the domain you want to file it into, but not the domain it is filed in now. Ask a steward of that domain to move it. Its owner can move it too, if they work in that domain.
Filing someone else's saved query is refused because its owner does not work in the domain Filing it there would leave the owner unable to edit their own query, so it is not allowed. File it into a domain its owner works in, or ask an administrator to add the owner's role group to that domain.

Arriving from a domain's detail page narrows this list to that domain automatically — a banner names it, with a one-click way back out. See Domains.

See also