Support
Log In

Migration Overview

Bring the business logic in your existing semantic layers — Looker, Tableau, Power BI, and more — into Credible as governed Malloy data models

You've probably already built a semantic layer — whether or not you call it one. And you may well have more than one: a Looker instance from one team, a Tableau data source from another, DAX measures in Power BI, a Snowflake semantic view — the sprawl that comes with acquisitions, multiple business units, or just different teams reaching for different tools. Each holds years of business logic your team trusts.

Credible helps you capture that meaning — from one tool or many — and consolidate it into governed data models in Malloy: readable, versioned in Git, and delivered as trusted context to every surface.

Your source model is prior art, not a spec to transpile line-for-line: the agent reads it for intent, keeps the logic worth keeping, drops what's tool-specific, and rebuilds the analytical domain as governed Malloy — running on the same open-source agent skills that power the rest of Credible, extended to read your source tool.

Migrate the Domain, Not the Dashboard

In practice there isn't one dashboard — there are dozens or hundreds, uneven in quality and usage, a handful carrying most of the traffic. Migration shouldn't recreate them tile for tile. Our migration approach anchors on the ones that matter and captures the analytical domain beneath them — the fields, metrics, and relationships actually in use, plus what they depend on — modeled by question rather than by tile, so the result rebuilds what those dashboards show and answers the follow-ups they imply. How sharply it can tell used from merely defined depends on the context: with query logs or usage reporting the trim is precise; otherwise the agent works from the data models and the SQL behind your key dashboards.

Scoping: The Field Survey

Before the four steps below, decide what is in scope. A model that has run for years exposes far more than anyone queries, and the trim is the difference between a migration that lands and one that stalls.

Work outward from a certified dashboard in three passes:

  1. Tile references — every field used in a tile's selects, filters, and sorts.
  2. Inline measures — the calculations defined on the tiles themselves rather than in the model. A surprising share of real business logic lives here.
  3. Ad hoc usage — fields people query that no dashboard touches, plus whatever those fields depend on, so nothing you keep points at something you cut.

Everything else is out. Where the source tool records its own usage — Looker's System Activity model is the clearest case — that trim is evidence rather than opinion.

From one migration. A certified dashboard of 28 tiles over three Looker explores: the explores exposed roughly 6,500 fields, the rebuilt model kept 377, and every supported tile was reproduced and validated row by row.

Structure the result by question, not by tile: base sources (one per physical table, no joins), then domain sources grouped by subject area, then named queries carrying #(doc) tags an agent can find by intent. Avoid a single "everything" source — cross-domain questions are better answered by an agent running several targeted queries than by one large join graph.

How It Works

Migration is the Collect step at full stretch. The meaning already exists — in your model code (LookML, TMDL, a YAML model, a semantic-view definition), in the dashboards and query logs built on it, and in the docs and decks written around it. The agent connects to wherever it lives and brings it in, including over the source's own APIs or MCP tools where those exist, so it can read the live model and validate against it.

Collecting context finds what is written down; it cannot find judgment. Your team supplies that while modeling, and the result hands off to the same Deliver path every model uses. The four steps:

Read

Inventory the source model — tables, dimensions, measures, joins, and the logic buried in calculated fields and filters.

Translate

Map each concept to its Malloy equivalent — sources, joins, dimensions, measures, views — keeping the logic and dropping tool-specific presentation and performance constructs.

Enrich

Add #(doc) and #(index) metadata tags — documenting what each field means and how to use it (units, rules, caveats) and indexing its values — so an agent finds the right field and uses it correctly.

Validate

Where a connection is available, run the model against live data and compare it row-by-row to the source's own engine — confirming a match before delivery.

The agent runs in the Credible App or in your IDE via local development — the same skills either way. A live connection isn't required to produce the model: without one you still get the full translation, ready to validate once a connection — the source engine or the warehouse behind it — is in place.

What the Agent Keeps, Skips, and Flags

Not every line in a source model belongs in the data model:

What it coversExamples
KeepBusiness logic and structureDimension and measure names, aggregation formulas, primary keys, joins, CASE logic, filtered aggregates, currency/percent formats
SkipDead weight & tool plumbingStale, redundant, or unused fields and reports; drill paths, action links, raw HTML and cosmetic styling
FlagJudgment calls for a humanLogic that may belong upstream (warehouse or dbt), synthetic primary keys, duplicate or conflicting field definitions

Presentation isn't ignored where it carries meaning: number and currency formats become render tags, a conditional-format rule ("flag when churn tops 10%") becomes model logic, and whole dashboards are rebuilt as data apps. What's genuinely dropped is what's dead — stale, redundant, or unused — or pure tool plumbing with no meaning. Where Malloy expresses something differently — DAX filter context, table calculations, metric_time — it's re-worked explicitly, never dropped silently; each source guide spells out how.

Proving Parity

When there's query access, the agent validates row-by-row — running each original metric through the source's engine (or equivalent SQL against the same warehouse) and diffing it against the migrated Malloy. Matching numbers confirm the translation; but a source of truth can carry its own errors, ambiguities, and inconsistencies, so any delta is confirmed and flagged for deeper investigation, not silently reconciled. It produces a coverage report — modeled, renamed, deferred, or skipped, each with a reason — plus any discrepancies it surfaced.

More Than a Reformat

A before/after looks like a translation — same metrics, cleaner syntax. That's the fidelity check; the reasons to migrate are what the new model can do that the old one couldn't:

  • It answers the next question. Malloy is composable — views nest, chain, and reuse as sources — so the model handles follow-ups the original dashboard never exposed.
  • AI-usable meaning. #(doc) and #(index) tags compressed into the engine's concept index tell an agent what a field means, how to use it, and what values it holds — so it finds the right field and queries it correctly, not just by matching a name.
  • Correct by construction. Malloy's symmetric aggregates stop measures double-counting across one-to-many joins — the silent bug in hand-written SQL and BI extracts.
  • It's real code, and it compiles. A typed language catches bad references and type mismatches at build time, not as wrong numbers in a dashboard — and it's concise, turning sprawling DAX or LookML into a few readable lines.
  • One model, every surface. One governed model serves agents over MCP, dashboards, data apps, and the REST APIs, with access control enforced at the gateway on every query — open, in Git, no lock-in.

A Worked Example

The payoff is a question the old dashboard couldn't answer — say, how revenue is pacing against target. With the sales domain modeled and a targets source joined in, that's one query:

#(doc) Monthly revenue vs. target, with attainment
query: revenue_vs_target is sales -> {
  group_by: order_month is order_date.month
  aggregate:
    actual is total_revenue
    target is targets.monthly_target
    # percent
    attainment is actual / target
}

Supported Sources

Each has a dedicated guide with a concept-to-Malloy mapping and a before/after: Looker, Sigma, Omni, Cube, Power BI, Tableau, Snowflake, dbt, and Databricks.

Don't see your tool? The same method applies to any semantic layer that exposes its definitions. Contact us and we'll walk through it.

Next Steps

On this page