Skip to content

Embedded analytics on Databricks: one dashboard, not five

Andrey Taran6 min read

Part 2 ended with a rule of one row-level dataset per dashboard, and it made each board fast. The next complaint from the client was about moving between boards.

Until then every one of the five client reports was its own AI/BI dashboard, embedded in the client's portal one at a time. That's how the reports had arrived from the Power BI days, one file per report, and we'd rebuilt them the same way without asking whether the split still made sense.

The moment it changed was the client's feedback after the first weeks of use. The numbers were right and each board was fast enough, and the thing they kept mentioning was the wait between reports. We merged the five reports into one dashboard behind one filter bar, kept the benchmark report separate, and tried and then reverted the pages feature along the way.

Below are the mechanics of an embedded dashboard switch, how the merged board is built, the rule we took from it, and the three places where the merge costs something. Like the rest of the series, it's an intermediate step in moving the application's client reporting onto Databricks.

Five reports, five iframes

We deliver the dashboards inside the client's portal through external embedding, and an embedded dashboard is an iframe. When a user switched from the sales report to the titles report, the portal asked our backend for a new embed token, Databricks rendered the dashboard shell from scratch under the service principal, and the datasets ran again. Databricks caches query results, so a second visit was quicker, but the shell still loaded, and the reports were reading the same two views anyway. A user paid a full page load to look at the same data from a different angle.

Portal

Embed token per report

Five iframes, five shell loads

Datasets run on every switch

One embed token

One dashboard, five sections

One global filter bar

Shared base query, warmed once

One dashboard with five sections replaces five embedded dashboards, so a report switch becomes a scroll instead of a new token, a new iframe and a new round of queries.

One dashboard, one filter bar

The fix didn't need a new feature. We put all five reports on one dashboard and one canvas, each report as a section, under a single global filter bar for the date range, the client and the state. Every remarketing dataset on the board opens with the same base query, the same join to the tenant scope table and the same four filters. One filter change therefore drives every section, and the shared client and state lists warm once. The five report builders kept their tested SQL, and the combined builder only reuses it.

What the user sees changed more than the SQL did. There's one embed token, one shell load and one filter bar, and all five reports sit one scroll apart. Today that board carries 18 datasets, and part 2 explains why it's 18 and not one.

What stayed separate

The benchmark report didn't join the combined board. It reads a different fact table, and merging it would have dragged its own datasets into every load of five reports that don't need them. That gave us the rule we now apply to new reports. Group dashboards by the fact table they read, not by the report name. If two reports read the same base, they belong on the same board. If they read different facts, separate boards are cheaper for everyone.

Pages, the experiment we reverted

AI/BI dashboards also have pages, rendered as tabs, and a dashboard runs only the datasets of the active page. We used that to make the raw-rows table lazy. The table moved to its own page, the board opened with charts only, and the row query fired the first time the tab was opened. The query counts confirmed it. On the titles board the initial load issued four queries without the rows dataset, and opening the tab issued two more.

We reverted it. Splitting the table from the charts put the rows one tab away from the numbers they explain, and the product owner preferred the table under the charts, loaded with them. The transform script stayed in the repository in case the trade-off is ever decided the other way. Pages are a real lever for load time, but they aren't free for the reader.

What the merge costs

  • The portal drives filters through the embed URL, with one parameter per page and widget. Those native filter widgets have to stay on the canvas with stable page and widget names, even though the portal clips that header and renders its own filter controls. Renaming a page breaks every binding the backend holds.
  • The rows preview and the complete CSV on the combined board are mixed-domain. Sold remarketing records and recent title activity share one list, so there's no single headline total that the rows add up to, and the export contract has to say so.
  • One board means one blast radius. A broken dataset now takes five reports down instead of one, which is why CI diffs every generated artifact against the committed one before it can be published.

Where it stands

This matches the original ticket better than five boards did. "Dynamic query and filter options" reads differently when every report answers to the same filter bar and sits one scroll away. The combined board is one step, and the next part of the series is about the client's request for real time, what it costs on a live database, and the compromise we settled on.

Frequently asked questions

Why not keep one dashboard per report and cache harder?

Caching helps the queries, not the shell. An embedded dashboard still needs its own token and its own iframe load on every switch, and that's the part users felt. One dashboard removes the switch itself, and the result cache then works for all five reports at once.

Doesn't one big dashboard load slower than a small one?

It loads once instead of five times, and the sections share one base query, so the extra cost is a few more datasets on the first load. Part 2 covers how we keep that count down and where it still bites, and the pages experiment above shows the lever we chose not to pull.

When should a report get its own dashboard?

When it reads a different fact table. Our benchmark report does, so it stayed separate, and the five reports that share a base stayed together. Grouping by fact table keeps each board's datasets relevant to every section on it.

Can pages replace sections?

They can, and a page runs only its own datasets, which makes lazy loading possible. We tried it for the raw-rows table and reverted it because readers wanted the table next to the charts. Pages fit when the content really is separate, and sections fit when the reader wants it in one view.