Migrate from Snowflake Semantic Views
Convert your Snowflake semantic views into governed Malloy data models
Snowflake semantic views and Malloy are close cousins — both are dimension, measure, and relationship graphs over SQL tables. Credible reads your semantic view definition, maps it almost concept-for-concept to Malloy, and — where you connect it — validates against Snowflake's own verified queries.
Still weighing the move? Credible vs. Snowflake Cortex sets the two side by side.
What Credible Reads
Your native SEMANTIC VIEW objects — logical tables, relationships, facts, dimensions, and metrics — or any legacy Cortex Analyst YAML models. The agent works from the exported definition (the CREATE SEMANTIC VIEW DDL or the YAML). Connecting to Snowflake — via SQL (DESCRIBE SEMANTIC VIEW, SHOW SEMANTIC VIEWS) or the Snowflake-managed MCP server (Cortex) — is optional: it lets the agent read views in place and run parity queries under Snowflake's own RBAC.
What Comes Across
The everyday modeling carries over. The bigger pieces land like this:
| In Snowflake | In Credible |
|---|---|
| Semantic view: logical tables & relationships | Malloy sources and joins |
| Dimensions, facts, metrics | Dimensions, row-level facts, and measures — facts feed measures, so you can re-aggregate at any grain |
WITH SYNONYMS / COMMENT | #(doc) / #(index), compressed into the engine's concept index |
| Verified queries | Parity fixtures and named views |
PUBLIC / PRIVATE, RBAC | Fine-grained access control in the model, versioned and enforced at the gateway on every query |
| Cortex Analyst / BI on top | Every surface — agents over MCP, data apps, notebooks, dashboards, APIs |
The Migration Flow
Credible reads the semantic view definition, translates logical tables and relationships to sources and joins (facts to row-level dimensions, metrics to measures), enriches with #(doc)/#(index) tags seeded from synonyms and comments, and — where you connect it — validates against Snowflake.
What Credible Handles
- Two coexisting formats — a deployment may use native
SEMANTIC VIEWobjects, legacy Cortex Analyst YAML on a stage, or both. Credible detects which and reads each accordingly. - Facts vs. metrics — a fact is a row-level expression; a metric is its aggregation. Credible keeps them distinct (fact → row-level dimension, metric → measure) so you can still re-aggregate at different grains. Collapsing them would lose that.
- Verified queries are the best thing to validate against — Credible replays each question→SQL pair and diffs the result against the migrated Malloy. (Verified SQL references logical names, not physical tables.)
Before & After
A CREATE SEMANTIC VIEW statement:
CREATE OR REPLACE SEMANTIC VIEW sales.sales_analytics
TABLES (
orders AS sales.orders PRIMARY KEY (order_id)
WITH SYNONYMS = ('purchase_orders')
COMMENT = 'Order transactions at the order grain',
customers AS sales.customers PRIMARY KEY (customer_id)
)
RELATIONSHIPS (
orders_to_customers AS orders (customer_id) REFERENCES customers (customer_id)
)
FACTS (
orders.line_amount AS orders.amount COMMENT = 'Per-row order amount in USD',
PRIVATE orders.is_shipped AS CASE WHEN orders.status = 'shipped' THEN 1 ELSE 0 END
)
DIMENSIONS (
orders.order_date AS CAST(orders.created_at AS DATE)
COMMENT = 'Date the order was placed',
customers.region AS customers.geographic_region
)
METRICS (
orders.total_revenue AS SUM(orders.line_amount) COMMENT = 'Total revenue in USD',
orders.shipped_revenue AS SUM(orders.line_amount * orders.is_shipped),
orders.shipped_revenue_pct AS
SUM(orders.line_amount * orders.is_shipped) / SUM(orders.line_amount)
);#(doc) Order transactions at the order grain. Also known as: purchase_orders
source: orders is conn.table('sales.orders') extend {
primary_key: order_id
join_one: customers is conn.table('sales.customers') on customer_id
dimension:
#(doc) Date the order was placed
order_date is created_at::date
#(doc) Per-row order amount in USD (fact)
line_amount is amount
#(doc) Row-level shipped flag (fact)
is_shipped is pick 1 when status = 'shipped' else 0
measure:
#(doc) Total revenue in USD
# currency
total_revenue is sum(line_amount)
#(doc) Revenue from shipped orders
# currency
shipped_revenue is sum(line_amount) { where: status = 'shipped' }
#(doc) Share of revenue that shipped
# percent
shipped_revenue_pct is shipped_revenue / total_revenue
}FACTS become row-level dimensions that feed measures; METRICS become measures. WITH SYNONYMS and COMMENT fold into #(doc) (Malloy has no synonym primitive, so alternate names go in the description for retrieval), and PRIVATE facts map to private: fields so they feed measures without being independently queryable. Don't map them to internal:, which a query can re-expose with extend.
More than a reformat. Semantic views map almost 1:1, so the gain is what surrounds them — composable follow-up queries, AI Analytics Engine discovery, and one model that reaches agents, apps, and BI beyond Cortex. See what you gain →