<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Krishna Tangudu</title>
    <description>The latest articles on DEV Community by Krishna Tangudu (@swaroop_krishna_e2f4b83b2).</description>
    <link>https://dev.to/swaroop_krishna_e2f4b83b2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3814074%2F3d7f150a-da32-48c6-9fda-dd6f74b170e2.jpeg</url>
      <title>DEV Community: Krishna Tangudu</title>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/swaroop_krishna_e2f4b83b2"/>
    <language>en</language>
    <item>
      <title>Ask Your Snowflake Account Anything — Build an AI Admin Agent with Cortex + GitHub Copilot ( Part 1 )</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Tue, 31 Mar 2026 15:57:14 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/ask-your-snowflake-account-anything-build-an-ai-admin-agent-with-cortex-github-copilot-1mk6</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/ask-your-snowflake-account-anything-build-an-ai-admin-agent-with-cortex-github-copilot-1mk6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — Spin up a Snowflake Cortex Agent that can answer admin questions like &lt;em&gt;"Which warehouses burned the most credits last month?"&lt;/em&gt; or &lt;em&gt;"Who are my top 5 spenders?"&lt;/em&gt; — all from a natural-language prompt inside GitHub Copilot Chat.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Snowflake &lt;code&gt;ACCOUNT_USAGE&lt;/code&gt; contains everything you need to understand spend, performance, and security. The catch? You have to know the right table, the right join, and write it correctly every time.&lt;/p&gt;

&lt;p&gt;What if you could just ask?&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub Copilot Chat
      │  (natural language)
      ▼
MCP Server (Python, local)
      │  ask_admin tool
      ▼
Snowflake Cortex Agent
      │  routes to the right semantic view
      ▼
SNOWFLAKE.ACCOUNT_USAGE (+ optional ORGANIZATION_USAGE)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the end you'll be able to type questions like these into Copilot Chat and get back answers with real numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;What are total compute credits by warehouse in the last 30 days?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Which users consumed the most credits this month?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How many failed logins occurred in the last 7 days?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;What are serverless credits by service type?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Snowflake account (any paid edition)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ACCOUNTADMIN&lt;/code&gt; or a role with &lt;code&gt;ACCOUNT_USAGE&lt;/code&gt; access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python 3.9+&lt;/td&gt;
&lt;td&gt;For the MCP bridge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VS Code + GitHub Copilot Chat&lt;/td&gt;
&lt;td&gt;Agent mode enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git&lt;/td&gt;
&lt;td&gt;To clone the template&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 1 — Clone the Template
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/LALITHASWAROOPK/agent_snowflake_admin_assistant.git
&lt;span class="nb"&gt;cd &lt;/span&gt;agent_snowflake_admin_assistant/agent_snowflake_admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the folder in VS Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2 — Deploy the SQL Objects (5 scripts, ~5 minutes)
&lt;/h2&gt;

&lt;p&gt;All SQL is in the &lt;code&gt;sql/&lt;/code&gt; folder. Replace the four placeholders before running:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Placeholder&lt;/th&gt;
&lt;th&gt;What to set&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;APP_DB&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A database to hold your views/agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;APP_SCHEMA&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Schema inside that database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ADMIN_ROLE&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Role that owns the objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;DEVELOPER_ROLE&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Role that will query the agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;EXEC_WAREHOUSE&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Warehouse the agent will use at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run them in order in a Snowflake worksheet or SnowSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="n"&gt;_create_views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;        &lt;span class="c1"&gt;-- Base views over ACCOUNT_USAGE&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;_create_semantic_views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;  &lt;span class="c1"&gt;-- Semantic layer (natural-language metadata)&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="n"&gt;_create_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;        &lt;span class="c1"&gt;-- Cortex Agent wired to those views&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="n"&gt;_create_budget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;       &lt;span class="c1"&gt;-- Optional: spending guardrails&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="n"&gt;_grants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;              &lt;span class="c1"&gt;-- RBAC grants&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What the Views Cover
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;01_create_views.sql&lt;/code&gt; builds seven base views, all sourced exclusively from &lt;code&gt;SNOWFLAKE.ACCOUNT_USAGE&lt;/code&gt; — no custom tables, no proprietary schemas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;View&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_WAREHOUSE_COST_BY_TAG&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;WAREHOUSE_METERING_HISTORY&lt;/code&gt; + &lt;code&gt;TAG_REFERENCES&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_QUERY_PERFORMANCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;QUERY_HISTORY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_USER_SPEND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;QUERY_ATTRIBUTION_HISTORY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_SERVERLESS_COSTS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tasks, pipes, clustering, search, MV refresh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_STORAGE_USAGE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;STORAGE_USAGE&lt;/code&gt; + &lt;code&gt;DATABASE_STORAGE_USAGE_HISTORY&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_LOGIN_HISTORY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;LOGIN_HISTORY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V_DATA_TRANSFER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DATA_TRANSFER_HISTORY&lt;/code&gt; + &lt;code&gt;REPLICATION_USAGE_HISTORY&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;02_create_semantic_views.sql&lt;/code&gt; wraps each base view with a &lt;code&gt;COMMENT&lt;/code&gt; block that tells the Cortex Agent what the view is for — this is how the agent knows which view to query for any given question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Semantic Views?
&lt;/h3&gt;

&lt;p&gt;Snowflake Cortex Agents use &lt;strong&gt;semantic views&lt;/strong&gt; as tool definitions. A semantic view is just a standard view with a &lt;code&gt;COMMENT&lt;/code&gt; that describes its purpose in natural language. The agent reads those comments at inference time to decide which tool (view) answers the user's question.&lt;/p&gt;

&lt;p&gt;No prompt engineering required on your end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 — Start the MCP Bridge
&lt;/h2&gt;

&lt;p&gt;The MCP (Model Context Protocol) server is a lightweight Python HTTP server that exposes one tool — &lt;code&gt;ask_admin&lt;/code&gt; — which Copilot Chat can call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; mcp/requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure your environment
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the repo root (never commit this):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SNOWFLAKE_ACCOUNT=&amp;lt;your_account&amp;gt;
SNOWFLAKE_USER=&amp;lt;your_user&amp;gt;
SNOWFLAKE_AUTHENTICATOR=externalbrowser
SNOWFLAKE_ROLE=&amp;lt;DEVELOPER_ROLE&amp;gt;
SNOWFLAKE_WAREHOUSE=&amp;lt;EXEC_WAREHOUSE&amp;gt;
SNOWFLAKE_AGENT_FQN=&amp;lt;APP_DB&amp;gt;.&amp;lt;APP_SCHEMA&amp;gt;.&amp;lt;AGENT_NAME&amp;gt;
MCP_PORT=3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Supports &lt;code&gt;externalbrowser&lt;/code&gt; (SSO), &lt;code&gt;snowflake&lt;/code&gt; (password), and OAuth — set &lt;code&gt;SNOWFLAKE_AUTHENTICATOR&lt;/code&gt; and the matching credential variable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Launch the server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;/scripts/start-mcp.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python mcp/server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify it's up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Invoke-RestMethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://127.0.0.1:3000/health&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# → {"status":"ok"}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4 — Connect Copilot Chat
&lt;/h2&gt;

&lt;p&gt;The repo ships a pre-configured &lt;code&gt;.vscode/mcp.json&lt;/code&gt; that wires the local MCP server into VS Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"snowflake-admin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3000"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VS Code picks this up automatically when you open the workspace. You'll see the &lt;code&gt;ask_admin&lt;/code&gt; tool listed inside Copilot Chat's tool picker.&lt;/p&gt;

&lt;p&gt;There's also a GitHub Copilot instruction file at &lt;code&gt;.github/instructions/admin.instructions.md&lt;/code&gt; which gives Copilot context about the agent's scope so it routes questions there automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5 — Ask It Questions
&lt;/h2&gt;

&lt;p&gt;Switch Copilot Chat to &lt;strong&gt;Agent mode&lt;/strong&gt; and try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What are my top 5 warehouses by compute credits in the last 30 days?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which users have spent the most credits this month?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Show me failed logins by user in the last 7 days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What serverless services are costing me the most right now?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What's my current storage usage broken down by database?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent selects the right semantic view, runs the query, and returns a plain-English answer with the numbers inline — no SQL, no context switching.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optional: Budget Guardrails
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;04_create_budget.sql&lt;/code&gt; sets up a Snowflake Budget object so you can enforce credit limits at the agent level. Handy for keeping a shared admin agent from running runaway queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CALL&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BUDGET_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;!&lt;/span&gt;&lt;span class="n"&gt;SET_SPENDING_LIMIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CALL&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BUDGET_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;!&lt;/span&gt;&lt;span class="n"&gt;GET_SPENDING_HISTORY&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Architecture Recap
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────┐
│         GitHub Copilot Chat         │
│      (Agent mode + ask_admin tool)  │
└────────────────┬────────────────────┘
                 │ HTTP / MCP
┌────────────────▼────────────────────┐
│      MCP Bridge  (mcp/server.py)    │
│  Exposes: /mcp/tools/list           │
│           /mcp/tools/call           │
│           /health                   │
└────────────────┬────────────────────┘
                 │ snowflake-connector-python
┌────────────────▼────────────────────┐
│   SNOWFLAKE.CORTEX.DATA_AGENT_RUN   │
│   ← Cortex Agent (semantic router)  │
└────────────────┬────────────────────┘
                 │ picks the right tool
┌────────────────▼────────────────────┐
│     Semantic Views (SV_*)           │
│     Base Views    (V_*)             │
│     ↑ SNOWFLAKE.ACCOUNT_USAGE       │
└─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Things to Know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Account Usage latency&lt;/strong&gt;: &lt;code&gt;SNOWFLAKE.ACCOUNT_USAGE&lt;/code&gt; is typically delayed by up to a few hours — not real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate sheet&lt;/strong&gt;: &lt;code&gt;ORGANIZATION_USAGE.RATE_SHEET_DAILY&lt;/code&gt; is optional and depends on your edition/region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth flexibility&lt;/strong&gt;: The MCP server supports SSO (&lt;code&gt;externalbrowser&lt;/code&gt;), OAuth, and password auth — configure once in &lt;code&gt;.env&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get the Code
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/LALITHASWAROOPK/agent_snowflake_admin" rel="noopener noreferrer"&gt;github.com/LALITHASWAROOPK/agent_snowflake_admin_assistant&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PRs and issues welcome. If you build on top of this, tag me — I'd love to see what you add.&lt;/p&gt;




</description>
      <category>snowflake</category>
      <category>githubcopilot</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>How Snowflake’s RELY Constraint Supercharges Your Star‑Schema Queries</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Thu, 19 Mar 2026 18:49:36 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/how-snowflakes-rely-constraint-supercharges-your-star-schema-queries-3n4f</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/how-snowflakes-rely-constraint-supercharges-your-star-schema-queries-3n4f</guid>
      <description>&lt;p&gt;Snowflake’s RELY constraint is a powerful but under‑used hint that tells the optimizer it can trust your primary keys and foreign keys and use them to eliminate unnecessary work—especially redundant joins. In this post, I’ll explain what RELY does, how it helps with join elimination, and walk you through concrete examples you can adapt for your own schemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters to a data engineer?
&lt;/h2&gt;

&lt;p&gt;If you’ve ever used wide, reusable models with hundreds of columns designed as a single source of truth, you know how easily queries can accumulate unnecessary joins. &lt;code&gt;RELY&lt;/code&gt; helps here by letting Snowflake eliminate redundant joins when they’re logically not needed, so queries only scan the tables that actually contribute to the result.&lt;/p&gt;

&lt;p&gt;In Snowflake, UNIQUE, PRIMARY KEY, and FOREIGN KEY constraints on standard tables are not enforced by default; they are mainly metadata for humans and tools. However, Snowflake lets you add a RELY property on those constraints to signal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I guarantee this constraint is true in my data, and you can use it to rewrite my queries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You set RELY like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_customer_id&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When does RELY kick in?
&lt;/h2&gt;

&lt;p&gt;Snowflake can use RELY‑tagged constraints to eliminate unnecessary joins when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A table has a PRIMARY KEY or UNIQUE constraint marked RELY.&lt;/li&gt;
&lt;li&gt;A related table has a FOREIGN KEY constraint also marked RELY.&lt;/li&gt;
&lt;li&gt;The query joins on those keys, but doesn’t actually need any columns from one of the joined tables beyond the key itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those situations, Snowflake can realize that the join is “logically redundant” and rewrite the plan to drop the table scan entirely.&lt;/p&gt;

&lt;p&gt;This is a cost-saving measure as it rewrites the query to eliminate unnecessary tables, allowing for faster performance. Additionally, may allows us to use a smaller warehouse may help reduce overall costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Simple join elimination with sample data&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;sale_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;sale_date&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_customer_id&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Charlie'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-01'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-05'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-03'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-04'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initial query (no RELY):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6n9d4azm0h36y04xh6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6n9d4azm0h36y04xh6y.png" alt=" " width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Plan:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcuhr14oh42dgth5mfg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcuhr14oh42dgth5mfg6.png" alt=" " width="591" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now enable RELY:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_customer_id&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, Snowflake sees:&lt;/p&gt;

&lt;p&gt;dim_customer.customer_id is unique and trusted (PRIMARY KEY RELY).&lt;br&gt;
fact_sales.customer_id is a trusted foreign key (fk_customer_id RELY).&lt;br&gt;
The only column used from dim_customer is customer_id, which is already in fact_sales.&lt;/p&gt;

&lt;p&gt;So the optimizer eliminates the join to dim_customer and rewrites the query plan like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs66gh5nrpdakxqp9ohf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs66gh5nrpdakxqp9ohf.png" alt=" " width="380" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result is identical, but the execution plan no longer scans dim_customer at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2: Join elimination with filters (and when it doesn’t kick in)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, dim_customer.customer_name is used in the filter, so the join on dim_customer is not redundant even with RELY. The optimizer must still fetch dimension data to evaluate the WHERE clause, so join elimination does not occur.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodpifee9z4xfa6tfx2y1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodpifee9z4xfa6tfx2y1.png" alt=" " width="633" height="669"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 3: RELY in a multi‑dimension star schema&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;  &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_channel&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;channel_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;sale_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;sale_date&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_customer&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_channel&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;dim_channel&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;##&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt; &lt;span class="k"&gt;Data&lt;/span&gt;

&lt;span class="c1"&gt;-- dimensions&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;dim_channel&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Online'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'In‑store'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- facts&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-01'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-02'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;103&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-01-03'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;##&lt;/span&gt; &lt;span class="n"&gt;Now&lt;/span&gt; &lt;span class="n"&gt;Enable&lt;/span&gt; &lt;span class="n"&gt;Rely&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dim_channel&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_customer&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt;
  &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_channel&lt;/span&gt; &lt;span class="n"&gt;RELY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run a query that only aggregates by fact keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;fact_sales&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dim_customer&lt;/span&gt; &lt;span class="n"&gt;d_c&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d_c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dim_channel&lt;/span&gt; &lt;span class="n"&gt;d_ch&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d_ch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, dim_channel and dim_customer are only used for their keys, which are already in fact_sales. With RELY, Snowflake can understand that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dim_customer.customer_id is unique and trusted.&lt;/li&gt;
&lt;li&gt;dim_channel.channel_id is unique and trusted.&lt;/li&gt;
&lt;li&gt;The join columns are already present in fact_sales.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it can eliminate both joins, effectively turning the query into:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff59c1tknvr8qxk7wvrj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff59c1tknvr8qxk7wvrj9.png" alt=" " width="404" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How RELY helps performance in practice&lt;/strong&gt;&lt;br&gt;
By enabling RELY on trusted PK/FK constraints, you give the optimizer permission to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Drop unnecessary dimensions from analytical queries that only reference key columns.&lt;/li&gt;
&lt;li&gt;Short‑circuit joins and reduce the number of operators in the plan, which often lowers merge‑join/hash‑join overhead.&lt;/li&gt;
&lt;li&gt;Reduce memory and compute usage, especially for large fact tables that are joined repeatedly in BI or ad‑hoc workloads.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important caveats and best practices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because RELY is a trust‑me hint, a few caveats matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are responsible for enforcing UNIQUE, PRIMARY KEY, and FOREIGN KEY constraints. If those constraints are violated, query results with RELY can differ from those with NORELY.&lt;/li&gt;
&lt;li&gt;Always validate data via ETL (e.g., dbt tests) before setting RELY, as violations can lead to suboptimal plans&lt;/li&gt;
&lt;li&gt;Timestamp_tz PKs or hybrid tables limit &lt;a href="https://community.snowflake.com/s/article/No-join-elimination-with-RELY-constraint-on-timestamp-tz-primary-key" rel="noopener noreferrer"&gt;elimination&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dataengineering</category>
      <category>performance</category>
      <category>snowflake</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Part 2: Zero-Copy data federation Snowflake Customer 360 Data to Salesforce Sales Reps</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Wed, 18 Mar 2026 18:00:00 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b</guid>
      <description>&lt;p&gt;In Part 1, we connected Salesforce Data Cloud to Snowflake for analytics. In this blog, you'll flip the direction: surface your Snowflake Customer 360 model (Orders, Service contracts, invoices, Repairs, etc.) directly into Salesforce so your sales and service teams can activate it in real time—without ETL or data duplication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Snowflake ↔ Salesforce Data Cloud ↔ Salesforce CRM
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snowflake&lt;/strong&gt;: Owns Customer 360 models, health scores, churn risk&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Zero-Copy&lt;/strong&gt;: Data Cloud queries Snowflake live (pushdown SQL)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Salesforce&lt;/strong&gt;: Activates signals (flows, UI, campaigns) &lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your data team builds 'CUSTOMER_360_VIEW' with 'ACCOUNT_ID', 'HEALTH_SCORE', 'CHURN_RISK', 'NEXT_BEST_PRODUCT'
&lt;/li&gt;
&lt;li&gt;Modeled once, governed in Snowflake (roles, masking, row access)
&lt;/li&gt;
&lt;li&gt;Updated via your ELT pipelines (daily/hourly)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Building data model in Snowflake
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="c1"&gt;-- ============================================================&lt;/span&gt;
&lt;span class="c1"&gt;-- COMPLETE DEMO SCRIPT: Accounts + Customer 360 + Final Table&lt;/span&gt;
&lt;span class="c1"&gt;-- ============================================================&lt;/span&gt;

&lt;span class="c1"&gt;-- Optional: set your context&lt;/span&gt;
&lt;span class="c1"&gt;-- USE ROLE &amp;lt;your_role&amp;gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- USE WAREHOUSE &amp;lt;your_warehouse&amp;gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- USE DATABASE &amp;lt;your_database&amp;gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- USE SCHEMA &amp;lt;your_schema&amp;gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;-- 1) Clean up old objects (safe for reruns)&lt;/span&gt;
&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT_C360_SNAPSHOT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER_360_METRICS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;-- 2) Create source tables&lt;/span&gt;
&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ACCOUNT_NAME&lt;/span&gt; &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;INDUSTRY&lt;/span&gt; &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ANNUAL_REVENUE&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;DELETED_AT&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMP_NTZ&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER_360_METRICS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;HEALTH_SCORE&lt;/span&gt; &lt;span class="nb"&gt;FLOAT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CHURN_RISK&lt;/span&gt; &lt;span class="nb"&gt;FLOAT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;NPS_SCORE&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;ARR&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;NEXT_BEST_PRODUCT&lt;/span&gt; &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LAST_ENGAGEMENT_DATE&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;-- 3) Insert sample data (toy companies)&lt;/span&gt;
&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INDUSTRY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ANNUAL_REVENUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DELETED_AT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bright Blocks Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Rocket Wheels Co'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;8000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1003&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Cuddle Critters Inc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1004&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Puzzle Planet Ltd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Old Toy Factory'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;5000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-15 10:00:00'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bad Row'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="s1"&gt;'Toys'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER_360_METRICS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEALTH_SCORE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CHURN_RISK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NPS_SCORE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ARR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NEXT_BEST_PRODUCT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LAST_ENGAGEMENT_DATE&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1800000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'STEM Robot Kit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="s1"&gt;'2026-03-10'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;650000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Turbo Track Racing Set'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'2026-03-05'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1003&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;420000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Deluxe Plush Care Pack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="s1"&gt;'2026-02-20'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1004&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Master Puzzle Collection'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2026-03-14'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;900000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Collector Train Set'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="s1"&gt;'2026-03-01'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;-- no matching account&lt;/span&gt;

&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="c1"&gt;-- 4) Create final table using your view definition logic&lt;/span&gt;
&lt;span class="c1"&gt;-- ------------------------------------------------------------&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT_C360_SNAPSHOT&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INDUSTRY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANNUAL_REVENUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HEALTH_SCORE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CHURN_RISK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NPS_SCORE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NEXT_BEST_PRODUCT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LAST_ENGAGEMENT_DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HEALTH_SCORE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Healthy'&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HEALTH_SCORE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'At Risk'&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'Critical'&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;HEALTH_STATUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CHURN_RISK&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'High'&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CHURN_RISK&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'Medium'&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'Low'&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;CHURN_RISK_LEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;LAST_UPDATED&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTS&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER_360_METRICS&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;C360&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_ID&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DELETED_AT&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data Cloud keeps a **virtual reference&lt;/strong&gt; to Snowflake views—no data duplication, always fresh**&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Connecting Salesforce Data Cloud to Snowflake using zero copy data federation
&lt;/h2&gt;

&lt;p&gt;First, review your network policies and ensure that Salesforce Data Cloud &lt;a href="https://help.salesforce.com/s/articleView?id=data.c360_a_data_cloud_ip_address_allowlist.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;IPs&lt;/a&gt; are included.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Salesforce Data Cloud connection:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsojl5fcs491eyc284o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsojl5fcs491eyc284o7.png" alt=" " width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaiipzojy7rnarrtzr2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaiipzojy7rnarrtzr2d.png" alt=" " width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Make sure the private key is unencrypted and eliminate comments, such as "BEGINNING OF PRIVATE KEY" and "END OF PRIVATE KEY".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a Snowflake Data Stream in Data Cloud:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjzkxym2fwram5z15u1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjzkxym2fwram5z15u1n.png" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Select the required object from Snowflake:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzkn35ap33m0r7lu6q4oq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzkn35ap33m0r7lu6q4oq.png" alt=" " width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure with below details:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Object Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Customer_360&lt;/td&gt;
&lt;td&gt;Simple, no special chars; this is the internal name Data Cloud uses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Accounts&lt;/td&gt;
&lt;td&gt;Helps organize data streams by business domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ACCOUNT_ID&lt;/td&gt;
&lt;td&gt;The unique identifier that joins to Salesforce Account records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Organization Unit Identifier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ACCOUNT_ID&lt;/td&gt;
&lt;td&gt;(Optional; keep same as Primary Key unless you have a multi-tenant model)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dskzr0jp1xt3fnx4of6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dskzr0jp1xt3fnx4of6.png" alt=" " width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Live/Schedule:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfm6x9s12z9n4kavkbjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfm6x9s12z9n4kavkbjp.png" alt=" " width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable Select Acceleration only when necessary.&lt;/strong&gt;&lt;br&gt;
This approach allows Salesforce to cache data on a scheduled basis instead of querying Snowflake for every request.&lt;br&gt;
When users attempt to load large volumes of data but only select a small subset of columns, querying Snowflake directly can become unnecessarily expensive. Leveraging Select Acceleration in these scenarios helps reduce compute costs and improves query performance by avoiding repeated full-table scans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstp1mklzrm11m44n0stz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstp1mklzrm11m44n0stz.png" alt=" " width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Salesforce as Activation Layer
&lt;/h2&gt;

&lt;p&gt;Sales reps see Snowflake signals in Account/Opportunity pages, flows create tasks automatically&lt;/p&gt;

&lt;p&gt;Maps &lt;code&gt;ACCOUNT_ID&lt;/code&gt; → Data Cloud profile, pulls &lt;code&gt;HEALTH_SCORE&lt;/code&gt;, &lt;code&gt;CHURN_RISK&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Live signals drive real-time actions without swivel-chair between BI and CRM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Queries fired by Salesforce can be monitored in snowflake in Query History:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhravdp6oy4ar102cch2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhravdp6oy4ar102cch2.png" alt=" " width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Governance &amp;amp; Ownership
&lt;/h2&gt;

&lt;p&gt;Snowflake: Data ownership, model logic, calculations&lt;br&gt;
Data Cloud: Unification, activation logic&lt;br&gt;
Salesforce: UX, workflows, business rules&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key patterns from production&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake auto-scaling handles Data Cloud query bursts&lt;/li&gt;
&lt;li&gt;Explicit 'GRANT SELECT' on views (not tables) for least privilege&lt;/li&gt;
&lt;li&gt;Data Cloud refresh schedule matches Snowflake pipeline cadence &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production Impact
&lt;/h2&gt;

&lt;p&gt;Before: Sellers export CSV from Snowflake → manual Salesforce upload&lt;br&gt;
After: Zero-copy signals → automatic tasks → faster CSM response&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Salesforce Data Cloud also provides an option for &lt;a href="https://developer.salesforce.com/docs/data/data-cloud-int/guide/c360-a-set-up-snowflake-file-federation-connection.html" rel="noopener noreferrer"&gt;file‑based federation&lt;/a&gt; when using the Snowflake Polaris Catalog Account.&lt;/p&gt;

&lt;p&gt;This enables data access without continuously querying Snowflake, offering an alternative integration pattern for specific use cases.&lt;/p&gt;

&lt;p&gt;Whether this capability will be extended to the Horizon Catalog remains to be seen—something to watch as the platform evolves.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>dataengineering</category>
      <category>salesforce</category>
      <category>snowflake</category>
    </item>
    <item>
      <title>Part 1: Zero-Copy Sharing – Salesforce Snowflake for Analytics</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Thu, 12 Mar 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/part-1-zero-copy-sharing-salesforce-snowflake-for-analytics-4f0j</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/part-1-zero-copy-sharing-salesforce-snowflake-for-analytics-4f0j</guid>
      <description>&lt;h2&gt;
  
  
  The ETL Nightmare Ends
&lt;/h2&gt;

&lt;p&gt;Salesforce holds your richest customer data—opportunities, accounts, contacts—but getting it into Snowflake for analytics usually means painful ETL pipelines, schema drift, and maintenance hell. Zero-copy data Federation sharing changes everything: Salesforce publishes secure shares that land in Snowflake as native objects, queryable instantly without duplication or latency.&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;We are currently in the process of implementing Salesforce Sales Cloud. In this first part of a 2-part series, I'll walk through the exact OAuth setup, common integration traps (network policies! URL underscores!), and best practices for analytics teams.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Zero-copy sharing flips traditional pipelines: Salesforce Data Cloud becomes the secure publisher, Snowflake the consumer.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Owner&lt;/th&gt;
&lt;th&gt;Contains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Salesforce Sales Cloud&lt;/td&gt;
&lt;td&gt;Raw CRM objects (OPPORTUNITY, ACCOUNT, CONTACT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Share&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Salesforce Data Cloud&lt;/td&gt;
&lt;td&gt;Secure data share with selected objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consumer DB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake&lt;/td&gt;
&lt;td&gt;Read-only shared objects like SFDC.OPPORTUNITY&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analytics Layer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake&lt;/td&gt;
&lt;td&gt;Views, models, dashboards built on shared data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Salesforce Datacloud handles object sharing; Snowflake analysts query familiar objects immediately. No Fivetran, no Airflow, no storage costs for duplicates.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step-by-Step Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before you begin:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure that your Snowflake admin adds the &lt;a href="https://help.salesforce.com/s/articleView?id=data.c360_a_data_cloud_ip_address_allowlist.htm&amp;amp;language=en_US&amp;amp;type=5" rel="noopener noreferrer"&gt;Data 360 IP Addresses&lt;/a&gt; to the allowlist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.salesforce.com/s/articleView?id=data.c360_a_data_shares_aws_supportability_snowflake.htm&amp;amp;type=5" rel="noopener noreferrer"&gt;Supported Regions for Snowflake Integration&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Snowflake&lt;/strong&gt;&lt;br&gt;
Step 1: Snowflake Security Integration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;sf_integration&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OAUTH&lt;/span&gt;
  &lt;span class="n"&gt;OAUTH_CLIENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOM&lt;/span&gt;
  &lt;span class="n"&gt;OAUTH_CLIENT_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'CONFIDENTIAL'&lt;/span&gt;
  &lt;span class="n"&gt;OAUTH_REDIRECT_URI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://test.salesforce.com/services/cdp/SnowflakeOAuthCallback'&lt;/span&gt;
  &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;
  &lt;span class="n"&gt;OAUTH_ISSUE_REFRESH_TOKENS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Prod tip: Swap test.salesforce.com for login.salesforce.com in production.&lt;br&gt;
​&lt;br&gt;
Step 2: Snowflake Integration User (Not required if the user creating a data target on Salesforce already has a login using Azure or a native user in Snowflake.)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;sf_integration_user&lt;/span&gt;
  &lt;span class="n"&gt;LOGIN_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sf_integration_user'&lt;/span&gt;
  &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;secure-password&amp;gt;'&lt;/span&gt;
  &lt;span class="n"&gt;DEFAULT_ROLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sf_integration_role'&lt;/span&gt;
  &lt;span class="n"&gt;EMAIL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your-email@company.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Grant&lt;/span&gt; &lt;span class="n"&gt;minimal&lt;/span&gt; &lt;span class="k"&gt;privileges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;warehouse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Step 3: Client Secrets &amp;amp; Salesforce Config&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SYSTEM&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;SHOW_OAUTH_CLIENT_SECRETS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sf_integration'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Copy both client ID and secret to Salesforce Data Cloud. &lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;Step 4: Salesforce Data Target&lt;br&gt;
Salesforce team configures:&lt;/p&gt;

&lt;p&gt;Account URL: &lt;a href="https://my-account-us-east-1.snowflakecomputing.com" rel="noopener noreferrer"&gt;https://my-account-us-east-1.snowflakecomputing.com&lt;/a&gt;&lt;br&gt;
Critical: if your Snowflake URL has underscores (my_account_us-east-1), convert to hyphens (my-account-us-east-1) in the Account URL field.&lt;/p&gt;

&lt;p&gt;Authentication: OAuth (using secrets from step 3)&lt;/p&gt;

&lt;p&gt;Step 5: Publish to Share:&lt;br&gt;
The Salesforce team should create a data stream and a data lake object, then add this object to the created Data Share Target.&lt;/p&gt;

&lt;p&gt;Data Stream ( Address ):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb7o5bivs1p5nla929ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwb7o5bivs1p5nla929ll.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data Lake Object: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel12xb7tl6on5zy9ua9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel12xb7tl6on5zy9ua9d.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Salesforce publishes share → Snowflake receives:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1nq8ux16yzgc1a34o5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1nq8ux16yzgc1a34o5h.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;sf_shared&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;SHARE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShareName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Integration Issues &amp;amp; Fixes&lt;/strong&gt;&lt;br&gt;
80% of failures happen here. Lessons from this activity:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network Policies Block Everything&lt;/strong&gt;&lt;br&gt;
Snowflake network policies can silently prevent Salesforce Data cloud IP ranges.&lt;br&gt;
Check: SHOW NETWORK POLICIES;&lt;br&gt;
Fix: Add Salesforce Data cloud IPs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account URL Underscores → Hyphens&lt;/strong&gt;&lt;br&gt;
Salesforce rejects Snowflake URLs with _. Always transform:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check Permissions&lt;/strong&gt;&lt;br&gt;
Check the permissions of the user who is trying to establish the connection&lt;/p&gt;

&lt;p&gt;Note: This setup is only required one time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Best Practices for Analytics Teams
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Layered Architecture&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SF_SHARED (raw, read-only)
↓
SF_ANALYTICS (views, materialized)
↓
BI tools (Power BI, Tableau)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Governance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable only semantic view access :
grant USAGE on raw share to business users&lt;/li&gt;
&lt;li&gt;Create weekly Alert to monitor Schema drift breaks downstream views
Salesforce owns object changes (new fields, deletions) &lt;/li&gt;
&lt;li&gt;Materialize frequent aggregates like below
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opp_pipeline_summary&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;avg_amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sf_shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sfdc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opportunity&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Cost&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Use multi-cluster warehouses for concurrent BI queries&lt;br&gt;
Monitor: QUERY_HISTORY() for expensive shared table scans&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take Away:&lt;/strong&gt;&lt;br&gt;
0 TB duplicated storage, 30% faster pipeline deployment, 100% schema fidelity.&lt;/p&gt;

&lt;p&gt;Quick Wins Checklist&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  URL underscores → hyphens&lt;/li&gt;
&lt;li&gt;[ ]  Network policy allows Salesforce IPs&lt;/li&gt;
&lt;li&gt;[ ]  Test OAuth token refresh before prod&lt;/li&gt;
&lt;li&gt;[ ]  Raw share → semantic views (don't expose raw)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's Next (Part 2 Teaser)&lt;br&gt;
This gets Salesforce data into Snowflake seamlessly. In Part 2, we reverse direction: Snowflake Customer 360 data flowing back to sales reps in Salesforce via data federation&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Start Your Integration
&lt;/h2&gt;

&lt;p&gt;✅ Fork: &lt;a href="https://github.com/LALITHASWAROOPK/salesforce-snowflake-zero-copy" rel="noopener noreferrer"&gt;https://github.com/LALITHASWAROOPK/salesforce-snowflake-zero-copy&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2 →&lt;/strong&gt; Customer 360 (Snowflake → Salesforce)&lt;br&gt;


&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b" class="crayons-story__hidden-navigation-link"&gt;Part 2: Zero-Copy data federation Snowflake Customer 360 Data to Salesforce Sales Reps&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/swaroop_krishna_e2f4b83b2" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3814074%2F3d7f150a-da32-48c6-9fda-dd6f74b170e2.jpeg" alt="swaroop_krishna_e2f4b83b2 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/swaroop_krishna_e2f4b83b2" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Krishna Tangudu
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Krishna Tangudu
                
              
              &lt;div id="story-author-preview-content-3365564" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/swaroop_krishna_e2f4b83b2" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3814074%2F3d7f150a-da32-48c6-9fda-dd6f74b170e2.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Krishna Tangudu&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b" id="article-link-3365564"&gt;
          Part 2: Zero-Copy data federation Snowflake Customer 360 Data to Salesforce Sales Reps
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cloud"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cloud&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dataengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dataengineering&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/salesforce"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;salesforce&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/snowflake"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;snowflake&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/swaroop_krishna_e2f4b83b2/part-2-reverse-zero-copy-activating-customer-360-in-salesforce-3c2b#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;/div&gt;





&lt;p&gt;Try this yourself: Share your biggest Salesforce-Snowflake integration pain point in the comments!&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>salesforce</category>
      <category>datacloud</category>
      <category>zerocopy</category>
    </item>
    <item>
      <title>Setting up Snowflake–Power BI Connectivity with Azure AD SSO and Auto-Provisioning</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Thu, 12 Mar 2026 14:18:02 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/setting-up-snowflake-power-bi-connectivity-with-azure-ad-sso-and-auto-provisioning-1gda</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/setting-up-snowflake-power-bi-connectivity-with-azure-ad-sso-and-auto-provisioning-1gda</guid>
      <description>&lt;h2&gt;
  
  
  Overview:
&lt;/h2&gt;

&lt;p&gt;This post walks through how to enable end-to-end SSO from Power BI to Snowflake using Azure AD, while automatically provisioning users and roles via SCIM. It’s designed for enterprise BI scenarios where analysts connect with DirectQuery or scheduled refresh and you want their Azure AD identity and group membership to control Snowflake access without manual user administration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Configure SSO to Snowflake with Azure AD
&lt;/h2&gt;

&lt;p&gt;Step 1.1:  Register Snowflake in Azure AD&lt;br&gt;
Ask your Azure team to register the Snowflake application in Azure AD using these values (replace with your account locator):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Identifier (Entity ID):
https://&amp;lt;account_locator&amp;gt;.snowflakecomputing.com/

Reply URL:
https://&amp;lt;account_locator&amp;gt;.snowflakecomputing.com/fed/login

Sign On URL:
https://&amp;lt;account_locator&amp;gt;.snowflakecomputing.com/

Sign Out URL:
https://&amp;lt;account_locator&amp;gt;.snowflakecomputing.com/fed/logout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 1.2:  Collect SAML metadata from Azure AD&lt;/p&gt;

&lt;p&gt;&lt;code&gt;EntityID&lt;/code&gt; in the form: &lt;a href="https://sts.windows.net/" rel="noopener noreferrer"&gt;https://sts.windows.net/&lt;/a&gt;/ → use as SAML2_ISSUER&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Location&lt;/code&gt; in the form: &lt;a href="https://login.microsoftonline.com/" rel="noopener noreferrer"&gt;https://login.microsoftonline.com/&lt;/a&gt;/saml2 → use as SAML2_SSO_URL&lt;/p&gt;

&lt;p&gt;&lt;code&gt;X509Certificate&lt;/code&gt; → use as SAML2_X509_CERT&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SAML2_PROVIDER&lt;/code&gt; → set to CUSTOM when Azure AD is the IdP&lt;/p&gt;

&lt;p&gt;Step 1.3: Create the SAML2 integration in Snowflake&lt;/p&gt;

&lt;p&gt;Run as &lt;code&gt;ACCOUNTADMIN&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;USE ROLE ACCOUNTADMIN;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AZURE_AD_SSO_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SAML2&lt;/span&gt;
  &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_ISSUER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;EntityID from metadata&amp;gt;'&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_SSO_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;Location from metadata&amp;gt;'&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_PROVIDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'CUSTOM'&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_X509_CERT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;X509 certificate&amp;gt;'&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_SP_INITIATED_LOGIN_PAGE_LABEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'AzureADSSO'&lt;/span&gt;
  &lt;span class="n"&gt;SAML2_ENABLE_SP_INITIATED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables browser SSO into Snowflake via Azure AD&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Enable Automatic Provisioning with SCIM
&lt;/h2&gt;

&lt;p&gt;2.1 Create functional Azure groups&lt;br&gt;
Have the support/AD team create AD groups following a functional-role naming convention, for example:&lt;br&gt;
​&lt;br&gt;
DEVELOPER-SNOWFLAKE&lt;br&gt;
ADMIN-SNOWFLAKE&lt;br&gt;
SUPPORT-SNOWFLAKE&lt;br&gt;
​&lt;br&gt;
These group names will become Snowflake role names via SCIM and act as default roles.&lt;/p&gt;

&lt;p&gt;Step 2.2: Create SCIM integration in Snowflake&lt;/p&gt;

&lt;p&gt;Run as ACCOUNTADMIN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTADMIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SYSADMIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;AAD_PROVISIONING&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SCIM&lt;/span&gt;
  &lt;span class="n"&gt;SCIM_CLIENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'azure'&lt;/span&gt;
  &lt;span class="n"&gt;RUN_AS_ROLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'AAD_PROVISIONER'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then generate the SCIM access token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SYSTEM&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;GENERATE_SCIM_ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AAD_PROVISIONING'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token validity is 6 months; you must regenerate it periodically.&lt;/li&gt;
&lt;li&gt;Add monitoring/alerting to renew before expiry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 2.3 Share SCIM details with Azure team&lt;br&gt;
​&lt;br&gt;
Tenant URL:&lt;br&gt;
https://.snowflakecomputing.com/scim/v2/&lt;/p&gt;

&lt;p&gt;Secret Token: The SCIM access token generated above&lt;/p&gt;

&lt;p&gt;They will configure the Snowflake enterprise app in Microsoft Entra ID (Azure AD) for automatic provisioning, following Microsoft’s “&lt;a href="https://learn.microsoft.com/en-us/entra/identity/saas-apps/snowflake-provisioning-tutorial" rel="noopener noreferrer"&gt;Configure Snowflake for automatic user provisioning with Microsoft Entra ID&lt;/a&gt;” tutorial.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3. Configure SSO from Power BI to Snowflake
&lt;/h2&gt;

&lt;p&gt;Step 3.1: Security Integration creation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;CM_SC_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_LOCATOR&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_SSO_POWERBI_SNFK&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EXTERNAL_OAUTH&lt;/span&gt;
  &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AZURE&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_ISSUER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;EntityID from Step 2 (https://sts.windows.net/.../)&amp;gt;'&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_JWS_KEYS_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://login.windows.net/common/discovery/keys'&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_AUDIENCE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'https://analysis.windows.net/powerbi/connector/Snowflake'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'https://analysis.windows.net/powerbi/connector/snowflake'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'upn'&lt;/span&gt;
  &lt;span class="n"&gt;EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'login_name'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;--UPN in Azure AD matches the login_name or email&lt;/span&gt;

&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;CM_SC_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_LOCATOR&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_SSO_POWERBI_SNFK&lt;/span&gt;
  &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;EXTERNAL_OAUTH_ANY_ROLE_MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ENABLE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- This allows additional roles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3.2 Grant Snowflake access for Power BI users&lt;br&gt;
Grant appropriate warehouse and database access to the Snowflake roles that are created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WAREHOUSENAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="nv"&gt;"DEVELOPER-SNOWFLAKE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATABASENAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="nv"&gt;"DEVELOPER-SNOWFLAKE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATABASENAME&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SCHEMANAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="nv"&gt;"DEVELOPER-SNOWFLAKE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DATABASENAME&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SCHEMANAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="nv"&gt;"DEVELOPER-SNOWFLAKE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3.3 Network policy and IP ranges&lt;/p&gt;

&lt;p&gt;If you use Snowflake network policies, ensure the policy allows:&lt;br&gt;
​&lt;br&gt;
Power BI service IP ranges&lt;br&gt;
Azure AD IP ranges&lt;br&gt;
Microsoft publishes updated IP ranges here:&lt;br&gt;
&lt;a href="https://www.microsoft.com/en-us/download/details.aspx?id=56519" rel="noopener noreferrer"&gt;https://www.microsoft.com/en-us/download/details.aspx?id=56519&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Using it from Power BI
&lt;/h2&gt;

&lt;p&gt;Once everything above is configured:&lt;br&gt;
​&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Power BI (Desktop or Service), use the Snowflake connector.&lt;/li&gt;
&lt;li&gt;Sign in with your Azure AD (organizational) account.&lt;/li&gt;
&lt;li&gt;The connector obtains an Azure AD token, which Snowflake validates via the EXTERNAL_OAUTH integration, mapping the upn claim to the Snowflake login_name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: &lt;br&gt;
If connecting using PowerBI Service, please use Server Name as all lower case, otherwise MS PBI interface gives weird errors.&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>powerplatform</category>
      <category>fabric</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Understanding Snowflake Virtual Warehouses</title>
      <dc:creator>Krishna Tangudu</dc:creator>
      <pubDate>Mon, 09 Mar 2026 09:28:08 +0000</pubDate>
      <link>https://dev.to/swaroop_krishna_e2f4b83b2/understanding-snowflake-virtual-warehouses-4p5l</link>
      <guid>https://dev.to/swaroop_krishna_e2f4b83b2/understanding-snowflake-virtual-warehouses-4p5l</guid>
      <description>&lt;p&gt;I did something that could have disrupted our production queries: I suspended all our Snowflake warehouses during a maintenance window. This action might have caused loading errors in our dashboards. Surprisingly, everything loaded perfectly, with results returning in mere milliseconds. This experience was not a fluke; it marked my first real "aha moment" about how fundamentally different Snowflake's architecture is from that of traditional data warehouses. &lt;/p&gt;

&lt;p&gt;After three years as a Snowflake architect, I've realized that truly understanding virtual warehouses isn't just about knowing T-shirt sizes or auto-suspend settings. It's about understanding an architecture that challenges everything we learned from legacy systems. &lt;/p&gt;

&lt;p&gt;This is Part 1 of a series where I'll share what I've learned in the trenches. Let's start with the fundamentals. ## The Discovery: Queries Without Compute? Here's what happened: Our BI team ran their morning reports. Warehouses were suspended. Queries succeeded. No compute credits consumed. How? &lt;/p&gt;

&lt;p&gt;**Three layers of caching saved us:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.Result Cache (24 hours)&lt;/strong&gt; - If someone ran the exact same query in the last 24 hours with no data and parameters (e.g., timezone ) changed then Snowflake returns the cached result. No warehouse needed. No cost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="n"&gt;COMPUTE_WH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;SNOWFLAKE_SAMPLE_DATA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;TPCH_SF10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;distinct&lt;/span&gt; &lt;span class="n"&gt;l_partkey&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;LINEITEM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When you run it for the first time, it will scan the required data as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggc9sbc0gg4hzz8zw4y1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggc9sbc0gg4hzz8zw4y1.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you execute the query again, it will utilize the result cache, as demonstrated below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs6lhgm58f9dttfgxkse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frs6lhgm58f9dttfgxkse.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Metadata Cache&lt;/strong&gt; - Simple aggregations like COUNT(*) or MIN/MAX on clustered columns? Often answered from metadata alone. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT COUNT(*) AS lineitem_rows FROM LINEITEM;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vrl0m3hqj0qxqkxjd5j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vrl0m3hqj0qxqkxjd5j.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Local Disk Cache&lt;/strong&gt; - When a warehouse does spin up, frequently accessed data sits in SSD cache for ultra-fast retrieval&lt;/p&gt;

&lt;p&gt;If I add another column to the existing query, it will attempt to use the local warehouse cache.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT distinct **l_orderkey, ** l_partkey FROM LINEITEM;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj719bbzxrampmo6ai5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj719bbzxrampmo6ai5q.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This taught me something critical: &lt;br&gt;
&lt;strong&gt;In Snowflake, your warehouse isn't your database. It's just a compute engine you rent when you need it.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Please refer to this article, which provides a great starting point for understanding caching in Snowflake.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://community.snowflake.com/s/article/Caching-in-the-Snowflake-Cloud-Data-Platform" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.snowflake.com%2Fwp-content%2Fthemes%2Fsnowflake%2Fassets%2Fimg%2Fcommunity%2Fcommunity-social-share.jpg" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://community.snowflake.com/s/article/Caching-in-the-Snowflake-Cloud-Data-Platform" rel="noopener noreferrer" class="c-link"&gt;
            Snowflake Community
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcommunity.snowflake.com%2Fresource%2Ffavicon%3Fv%3D2"&gt;
          community.snowflake.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  What Actually Is a Virtual Warehouse?
&lt;/h2&gt;

&lt;p&gt;Think of virtual warehouses as ephemeral compute clusters that live completely separately from your data. &lt;strong&gt;Traditional warehouse:&lt;/strong&gt; Compute + Storage = One monolithic system &lt;strong&gt;Snowflake warehouse:&lt;/strong&gt; Compute ← (network) → Storage (separate, scalable independently) This separation is Snowflake's superpower. Your data lives in cloud storage (S3, Azure Blob, GCS). Warehouses are just compute resources that: - Spin up in seconds - Process queries - Shut down automatically - Scale independently of storage You can have 10 warehouses querying the same table simultaneously. Or zero warehouses with your data perfectly safe. &lt;/p&gt;

&lt;h2&gt;
  
  
  The T-Shirt Sizing Reality Snowflake offers warehouse sizes from X-Small to 6X-Large.
&lt;/h2&gt;

&lt;p&gt;After architecting systems at Agilent, here's what I've learned: &lt;br&gt;
&lt;strong&gt;X-Small (1 credit/hour):&lt;/strong&gt; - Perfect for: Dev/test, lightweight ETL, ad-hoc queries - What surprised me: Handles 80% of analytics workloads just fine - Common mistake: Over-provisioning because "bigger is safer" &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Medium to Large (4-8 credits/hour):&lt;/strong&gt; - The sweet spot for most adhoc complex production workloads - We scale up based on actual performance, not assumptions - One architect rule: If you need Larger size, first ask if you can optimize the query - Real example: We reduced a Medium job to X-Small by fixing a Cartesian join and using clustering &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The counterintuitive truth:&lt;/strong&gt; A bigger warehouse doesn't always mean faster queries. Sometimes it's a sign of inefficient SQL. &lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-Suspend: The Feature That Saves Careers (and Budgets) Set &lt;code&gt;AUTO_SUSPEND = 60&lt;/code&gt; (seconds) on every warehouse.
&lt;/h2&gt;

&lt;p&gt;No exceptions. In my first month, I found warehouses left running overnight resulting in wasted spend. The dev team didn't realize that unlike traditional databases, Snowflake warehouses don't shut down automatically when queries finish. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My standard configuration:&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;AUTO_SUSPEND = 60 -- Suspend after 1 minute of inactivity AUTO_RESUME = TRUE -- Restart automatically when needed&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 One minute feels aggressive, but remember: warehouses restart in seconds, and the result cache covers most repeat queries anyway. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real impact:&lt;/strong&gt; This simple change cut our development environment costs by 20%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For DevOps, DataOps, and Data Science use cases, Snowflake recommends setting auto-suspension to approximately 5 minutes because the cache is not as important for ad-hoc and unique queries.&lt;/li&gt;
&lt;li&gt;For query warehouses, for example BI and SELECT use cases, Snowflake recommends setting auto-suspend to at least 10 minutes to maintain the cache for users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://docs.snowflake.com/en/user-guide/performance-query-warehouse-cache" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;docs.snowflake.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


 

&lt;h2&gt;
  
  
  Auto-Resume: Trust It When &lt;code&gt;AUTO_RESUME = TRUE&lt;/code&gt;,
&lt;/h2&gt;

&lt;p&gt;suspended warehouses wake up automatically when queries arrive. Resume time? Usually 3-5 seconds based on size. Early in my Snowflake journey, I was nervous about this. What if a critical dashboard times out during resume? &lt;strong&gt;Three years later:&lt;/strong&gt; I've never seen this cause a production issue. The resume is fast, and users don't notice. Your anxiety about suspended warehouses is costing you money. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Misconceptions I Had (And Still Hear)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Misconception #1:&lt;/strong&gt; "Keep warehouses running for better performance" &lt;strong&gt;Reality:&lt;/strong&gt; Cold start is 3-5 seconds. Keeping a Medium warehouse running 24/7 wastes ~$2,000/month on Enterprise edition. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception #2:&lt;/strong&gt; "Bigger warehouses = faster queries" &lt;br&gt;
&lt;strong&gt;Reality:&lt;/strong&gt; Badly written queries stay slow regardless of size. Fix the SQL first. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception #3:&lt;/strong&gt; "We need one big warehouse for everything" &lt;strong&gt;Reality:&lt;/strong&gt; Multiple specialized warehouses provide better isolation and cost control. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Misconception #4:&lt;/strong&gt; "Warehouse size determines storage capacity" &lt;strong&gt;Reality:&lt;/strong&gt; Storage is completely independent. An X-Small can query petabytes. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Architect's Perspective: How This Changes Design Understanding warehouses changed how I design data systems:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Workload Isolation&lt;/strong&gt; Instead of one shared warehouse, we run: - ETL_WH (X-Small, auto-suspend 60s) - ANALYTICS_WH (Small, auto-suspend 60s) - REPORTING_WH (Small, multi-cluster for BI tools) - DEV_WH (X-Small, auto-suspend 30s) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; A poorly optimized dev query can't impact production reports. Each team pays for what they use. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cost Attribution&lt;/strong&gt; Tagged warehouses let us track costs by department, project, or team. Finance loves this. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Right-Sizing Strategy&lt;/strong&gt; Start small. Scale up only when performance metrics justify it. We monitor query execution time and queuing, not gut feelings. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Embrace Suspension&lt;/strong&gt; Our warehouses spend 90% of their time suspended. That's not a problem—it's efficient architecture. ## What's Coming in This Series Over the next few weeks, I'll dive deeper: &lt;strong&gt;Part 2:&lt;/strong&gt; Warehouse Optimization &amp;amp; Cost Control (multi-cluster warehouses, scaling policies, cost monitors) &lt;strong&gt;Part 3:&lt;/strong&gt; Advanced Patterns (workload management, query acceleration, clustering, search optimization) &lt;strong&gt;Part 4:&lt;/strong&gt; Monitoring &amp;amp; Troubleshooting (the queries I run daily, how to spot inefficiencies) &lt;strong&gt;Part 5:&lt;/strong&gt; Iceberg Lakehouse Architecture &lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;After three years architecting on Snowflake, here's what I tell every new team: Virtual warehouses aren't databases. They're temporary compute resources you rent by the second. The moment you internalize this, everything else clicks into place. &lt;/p&gt;

&lt;p&gt;That suspended warehouse isn't "off"—your data is still there, your caches are warm, and your next query is just 3 seconds away from full compute power. Stop treating Snowflake like it's Oracle or HANA. Start treating warehouses like the elastic, ephemeral resources they are. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's been your biggest "aha moment" with Snowflake? &lt;br&gt;
Comment your cache gotcha!&lt;/strong&gt; —I learn as much from your experiences as you might from mine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let me know when you drop a warehouse from Snowflake. Will the result cache still work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Found this helpful? Follow me for Part 2 on warehouse optimization and cost control strategies.&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>dataarchitecture</category>
      <category>clouddatawarehouse</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
