Migrate from Cube
Convert your Cube cubes and views into governed Malloy semantic models
Cube and Credible share a worldview: a governed layer of measures, dimensions, and joins over your warehouse, queried by intent rather than raw SQL. That makes migration clean — Credible reads your Cube data model and rebuilds it as Malloy, keeping the semantics and shedding the engine-specific tuning.
What Credible Reads
Your Cube data model — cubes and views authored in YAML or JavaScript. Point the agent at those files and it has everything it needs to translate. Connecting Cube's MCP server (hosted per tenant over OAuth) or its SQL/REST/GraphQL APIs is optional: it lets the agent read the governed catalog directly and validate results against the live model.
What Comes Across
The everyday modeling carries over. Here's how the bigger pieces land — and where they get better:
| In Cube | In Credible |
|---|---|
| Cubes & views | Malloy sources (base + curated); import/export and explores govern exposure |
| Dimensions, measures, segments | Carried over — measures, dimensions, and reusable where: filters |
| Pre-aggregations | Dropped — Malloy queries live data, so rollup caches aren't carried over |
| Data access policies / member security | Fine-grained access control in the model, versioned and enforced on every surface |
title / description | #(doc) / #(index), indexed by the AI Analytics Engine |
| Dashboards built on Cube | Rebuilt as data apps or notebooks |
The Migration Flow
Credible reads the model, translates cubes to base sources and views to curated sources, enriches each field with #(doc)/#(index) tags, and — where you connect it — validates row-by-row against Cube's SQL API.
What Credible Handles
- Pre-aggregations accelerate the engine but carry no semantics — Malloy queries the warehouse live, so rollup caches are dropped. Parity is checked against raw data (a stale pre-agg can differ from the source of truth).
- JavaScript-defined models — dynamic cubes and templated generation are read through Cube's SQL/REST metadata rather than static file parsing.
- Data access policies (member-level security,
queryRewrite) map to Malloy access control rather than a 1:1 mechanism.
Before & After
cubes:
- name: orders
sql_table: sales.orders
description: All customer orders
joins:
- name: customers
relationship: many_to_one
sql: "{CUBE.customer_id} = {customers.customer_id}"
dimensions:
- name: order_id
sql: order_id
type: number
primary_key: true
- name: status
description: Current fulfillment status of the order
sql: order_status
type: string
measures:
- name: total_revenue
description: Total revenue in USD
sql: amount
type: sum
format: currency
- name: cancelled_orders
type: count
filters:
- sql: "{CUBE}.status = 'cancelled'"
- name: cancellation_rate
sql: "1.0 * {cancelled_orders} / NULLIF({count}, 0) * 100"
type: number
format: percent
pre_aggregations: # dropped — engine acceleration
- name: orders_rollup
measures: [count, total_revenue]
time_dimension: created_at
granularity: daysource: orders is conn.table('sales.orders') extend {
primary_key: order_id
join_one: customers is conn.table('sales.customers') on customer_id
dimension:
#(doc) Current fulfillment status of the order
#(index)
status is order_status
measure:
#(doc) Number of orders
order_count is count()
#(doc) Total revenue in USD
# currency
total_revenue is sum(amount)
#(doc) Orders that were cancelled
cancelled_orders is count() { where: status = 'cancelled' }
#(doc) Percentage of orders that were cancelled
# percent
cancellation_rate is cancelled_orders / order_count * 100
view:
#(doc) Daily orders and revenue trend
daily_orders is {
group_by: created_at.day
aggregate: order_count, total_revenue
}
}More than a reformat. The model queries live data (no pre-aggregation staleness), is AI-discoverable through the AI Analytics Engine, and serves agents, apps, and BI — not just Cube's APIs. See what you gain →