We're live on Product Hunt right now! Come support our launch

rocket logo for website pages

Winner of the 'Embedded Analytics Solution of the Year' at the '24 Data Breakthrough Awards.

Performant Embedded Analytics at Scale with Pre‑Aggregations

Contents

Looking for an embedded analytics tool?

Embeddable embeds in minutes, loads in milliseconds and extends infinitely - enabling you to deliver lightning-fast dashboards that feel native.

Find out more

Your customer-facing dashboards don’t get slow because SQL forgot how to compute. They get slow because every dashboard element asks the warehouse to re-read history.

Embedded dashboards are a growth feature. They lift product adoption, deepen customer engagement, and put insight where decisions happen - inside your app. That means lots of people accessing data, which increases the load from your data requests, and raises the bar for latency: more viewers, more filters, more “just refresh it.”

Ultimately it‘s hard to maintain performance on your customer-facing dashboards at scale

Pre‑aggregations change the unit of work. Instead of counting from raw events every time, you do the math once and serve the answer many times. Embeddable uses Cube for the data modelling layer, where you can set up pre‑aggregations - so you get the engagement benefits of embedding dashboards without the speed tax.

The growth trap

Without pre-aggregations, all data loading requests from your charts will hit your database(s) directly every time.

This has the advantage that users will always see the latest (up-to-date) data directly from the database. However, when a lot of concurrent users are viewing your dashboards at the same time, this can quickly mean a high load on your databases, which may affect their performance (both in terms of response time and financial cost):

  1. for OLTP (row-based) databases like Postgres, MySQL and SQLServer it can mean that some queries take too long to come back, as these databases are optimised for row-based lookup, not columnar aggregates.
  2. for OLAP (columnar) databases like Snowflake, BigQuery and Redshift it can mean significant financial costs in serving those incoming queries.
  3. in both cases, depending on your data, a query may simply require processing of many rows of data in order to answer an incoming data request.

At 10 million rows, a daily chart might feel like it loads fast. At 10 billion, the same chart becomes an apology. Nothing “broke.” You simply asked a detailed dataset to answer a coarse question - again and again.

You can feel the trap when:

  • The first person to open a dashboard waits longer because the cache is empty; subsequent viewers are faster.
  • All‑hands meetings turn into concurrency stress tests.
  • Adding a simple filter (“last 6 months”, “country = US”) behaves like a full rebuild of truth.

Embedding makes this problem visible because the same chart is opened by many users at once. Latency isn’t private anymore.

A simple mental model

Think of raw data as microfiche in an archive. You can find anything, but you’ll scroll for it. A pre‑aggregation is today’s front page: the things people ask for most, already summarized, ready to read.

Two moves are happening:

  1. Change the granularity. From billions of events to thousands of daily totals.
  2. Move the work in time. Compute when data lands, not when a human clicks.

A quick metaphor

Pre‑aggregations are like a well‑run quick‑service kitchen. The prep is done - ingredients portioned, sauces reduced, stations stocked - so when the order arrives it’s assemble + quick sear. Quality stays high because the craft happened upstream. If you truly need a slow, exploratory tasting menu, you can still cook à la minute from raw; for everyday dashboards, great food fast is the point.

An illustrative scale‑check

Question: “Daily active users for the last 180 days.”

  • Raw path: read ~3.6 billion event rows (20M/day × 180), then group by day.
  • Pre-agg path: read 180 rows - one per day for 180 days. Because the data is already rolled up to the daily grain, the pre-aggregation stores a tiny record per day (date, daily_active_users). New days append as they land, history stays fixed. When the dashboard loads, it simply reads those 180 records and renders - no heavy group-by over events, no full-table scan.

Same answer shape. ~20,000×80,000× less to read depending on your exact event rate. If you later add a dimension like country, you still only read about 45,000 rows (180 days × ~250 countries) - orders of magnitude smaller than raw.

This is what users experience as “fast.” It’s not a trick; it’s right‑sizing the work.

What changes when you embed

Embedded dashboards add two pressures:

  • Concurrency. Ten customers open the same page; ten heavy queries is a denial‑of‑service against your own warehouse. Pre‑aggregations turn those into light lookups.
  • Personalisation. Each viewer sees their own slice (filters, roles, regions). Naive caches collapse under that variety; rollups that match the question’s shape survive it - time grain, key dimensions, and common filters baked in.

Result: fewer full scans and more predictable latency when many people look at “the same chart, slightly different.”

How Embeddable uses Cube

Essentially: Pre-aggregations allow you to run most of the query in advance of the user requesting the data, so that the incoming queries have less work to do to return a result (which in turn means fast results).

Embeddable leans on Cube to maintain small, purpose‑built 'rollups'. Queries automatically hit the smallest rollup that fits; only true edge cases fall back to raw data requests. Updates arrive incrementally, so yesterday’s totals refresh without touching last month. When definitions evolve, rollups can be versioned instead of silently drifting.

The effect is simple: warm starts become the norm, cold starts shrink, and dashboards stay stable under load.

Why not DIY?

You can build this yourself - but it’s a lot. Rolling your own means engineering and operating: rollup tables, partitioning, incremental refresh logic, schedulers, backfills, cache invalidation, versioning, access controls, and monitors. Every change to a definition becomes a mini‑migration.

With Embeddable + Cube, it’s a handful of configurations in the data modeling layer: name the measures and dimensions, choose time grain and partitions, set the freshness schedule, and (optionally) enable external storage. The platform handles building, matching, pruning, refreshing, and fallbacks.

When teams skip rollups: predictable pain

  • Load time creep. A dashboard that launched at 800 ms quietly becomes 4–6 s as data grows.
  • Concurrency blowups. All‑hands or customer demos trigger timeouts and retried queries.
  • Cost surprises. Scanning history for every view turns into a compute bill with commas.
  • Fragile iteration. Product teams hesitate to add charts because each one adds load.

Pre‑aggregations aren’t an optimisation flourish; they’re the difference between a dashboard you’re proud to show and one you hide.

Why this matters now

Data generation grows faster than your tolerance for waiting. Storage is cheap, instrumentation is everywhere, and “just run it on the warehouse” feels fine - until volume, variety, and viewers converge. Pre‑aggregations keep the reader’s grain aligned with the system’s cost, so speed scales with you instead of against you.

Practical guardrails

These aren’t step‑by‑steps; they’re the small constraints that keep an essay honest when it meets production:

  • Start from the question, not the table.
  • Aggregate at the grain users read, not the grain systems write.
  • Accept small, explicit staleness in exchange for big, predictable speed.
  • Align rollups to common personalisation keys (e.g., tenant, plan, region) so the engine can prune work.
  • Version definitions when meaning changes; retire old ones on purpose.

Speed isn’t a feature tacked onto dashboards at the end. It’s a choice about when and where the math happens. Pre‑aggregations make that choice obvious: do the expensive work once, serve it cheaply forever. With Embeddable + Cube, that isn’t a platform rewrite. It’s the difference between a dashboard that apologises and one that invites you to keep exploring.

Next Steps

So, now you know why your dashboards are loading slower as you scale, and that pre-aggregations are a very effective way to handle it.

You can find our more about how pre-aggregations work in our caching docs , or explore more about Embeddable first.

If you need help with pre-aggregations, or want to chat generally about data performance at scale, I'm available in Embeddable's Slack Community.

Looking for an embedded analytics tool?

Embeddable embeds in minutes, loads in milliseconds and extends infinitely.

Get access