Cube is a semantic layer: a place to define metrics, dimensions, and joins once, in one modelling layer, so every dashboard, BI tool, and ad-hoc query downstream computes "revenue" or "active users" the same way instead of each consumer reimplementing the SQL slightly differently. The value shows up the first time two dashboards built by two different teams stop disagreeing about a number that should be the same.
The core idea: cube schema
A Cube schema defines a "cube" per fact table (or logical entity) with measures (aggregations — sums, counts, averages) and dimensions (things you group or filter by). Once defined, Cube generates SQL from a higher-level query — you ask for a measure grouped by a dimension over a time range, and Cube compiles that into the actual SQL against your warehouse, handling the join logic so consumers never write raw SQL against the underlying tables directly.
cube('Orders', {
sql: `SELECT * FROM public.orders`,
measures: {
count: { type: 'count' },
totalRevenue: { sql: 'amount', type: 'sum' },
},
dimensions: {
status: { sql: 'status', type: 'string' },
createdAt: { sql: 'created_at', type: 'time' },
},
joins: {
Customers: {
relationship: 'belongsTo',
sql: `${CUBE}.customer_id = ${Customers}.id`,
},
},
});
Pre-aggregations are the performance lever
Querying a raw fact table with millions of rows for every dashboard load is slow and expensive on the warehouse. Cube's pre-aggregation feature lets you define a rollup — a smaller, pre-computed summary table, refreshed on a schedule — that Cube automatically routes matching queries to instead of hitting the raw table. A dashboard asking for daily revenue by region can be served from a pre-aggregated daily-by-region rollup in milliseconds instead of scanning the full orders table on every page load. Getting pre-aggregations right (which measures, which dimensions, what refresh cadence) is usually the single biggest lever on both query latency and warehouse cost.
A pre-aggregation refreshed hourly means dashboards built on it are up to an hour stale. That's fine for most business dashboards and wrong for an operational view that needs near-real-time numbers. Set refresh cadence per pre-aggregation based on what each specific metric actually needs, not one global default.
One model, many consumers
Cube exposes the modelled semantic layer over multiple APIs — a SQL API that BI tools (Tableau, Looker Studio, Power BI) can connect to as if Cube were just another Postgres-compatible database, a REST/GraphQL API for custom dashboards, and native integrations for embedding charts directly in an application. The pattern this enables: business logic like "what counts as an active customer" or "how do we calculate churn" gets defined once in the Cube schema, and every consumer — the exec dashboard, the customer-facing usage widget, the ad-hoc analyst query — inherits the same definition instead of each team encoding it independently and drifting apart over time.
Access control at the semantic layer
Because every query routes through Cube, row-level and column-level security can be enforced centrally rather than duplicated in every dashboard tool's own permission system. A multi-tenant SaaS product can inject the current tenant ID into the security context and have Cube automatically scope every query to that tenant, which removes an entire class of "someone forgot to add the WHERE clause in this one dashboard" data leak.
The fastest way to prove Cube's value is to find the one metric that's currently defined slightly differently in three different dashboards — revenue, active users, whatever it is — model it once in Cube, and point all three consumers at that single definition. That concrete "the numbers finally match" moment is a stronger case for broader adoption than modelling the entire schema upfront.
| Layer | Without a semantic layer | With Cube |
|---|---|---|
| Metric definitions | Duplicated per dashboard, drift over time | Defined once, consumed everywhere |
| Query performance | Every dashboard hits raw tables | Pre-aggregations serve common queries fast |
| Access control | Enforced per-tool, inconsistently | Enforced centrally in the security context |
| New BI tool onboarding | Re-derive all metric logic from scratch | Connect to Cube's SQL API, inherit existing models |
Wrapping up
Cube earns its place when the same metric is being recomputed slightly differently across multiple dashboards and tools — that's the specific pain it's designed to remove. Model one high-value, currently-duplicated metric first, get pre-aggregations tuned for its actual freshness needs, and expand the schema from there rather than trying to migrate an entire warehouse's worth of metrics into it up front.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.