FlowKit

Connecting Snowflake to n8n: SQL queries, warehouse cost and traps

Published 26 August 2026 · 8 min read

n8n is not an ETL tool: it will not replace Fivetran for replicating a source, nor dbt for building versioned, tested SQL models. Its place around a Snowflake warehouse is elsewhere, and it is a real one — orchestrating the last mile: firing a query at the right moment, pushing the result to a business team, feeding a table from an API no connector covers, reacting when a number drops. This guide covers the native node, its credential, the REST SQL API for what the node cannot do, and the subject that decides everything here: cost.

The Snowflake credential

The snowflake credential bundles session context and authentication:

  • Account: the identifier sitting between https:// and snowflakecomputing.com in your Snowflake URL — the organisation-account form (mycorp-ab12345) on recent accounts, a regional identifier such as ab12345.eu-west-1 on older ones.
  • Database, Schema, Warehouse, Role: the context applied on connection. These four fields decide what your queries can see and which cluster runs them.
  • Authentication: Password (with Username and Password) or Key-Pair, which expects a Private Key in PEM PKCS#8 format plus an optional Passphrase — the node then switches the driver's authenticator to SNOWFLAKE_JWT.
  • Origin Hostname: an alternative hostname, useful behind PrivateLink.
  • Client Session Keep Alive: keeps the client connection open indefinitely, where it would otherwise expire after three to four hours of inactivity. It applies to the session, not the warehouse.

The node adds its own Authentication parameter, choosing between Credentials and OAuth2 (a separate snowflakeOAuth2Api credential). Create a dedicated service user, with a read-only role — USAGE on the warehouse and schema, SELECT on the views — for any reporting workflow. The discipline that applies to any API credential applies here too: ACCOUNTADMIN sitting in a shared workflow is a vulnerability, not a shortcut.

The node's three operations

The n8n-nodes-base.snowflake node exposes Execute Query, Insert and Update. There is no Snowflake trigger: everything starts from a Schedule Trigger, a webhook or another node.

Execute Query takes a Query field with a dedicated SQL editor, plus an Options section holding Query Parameters: a comma-separated list of values bound to the positional placeholders in the query.

SELECT customer_id, SUM(amount) AS revenue
FROM orders
WHERE order_date >= ? AND status = ?
GROUP BY customer_id

The hint under the field spells out the placeholder syntax your node version expects — documentation and code have diverged here, so trust your own instance. The principle does not change: values reach the driver as binds, never concatenated. A hand-written WHERE email = '{{ $json.email }}' remains an SQL injection waiting to happen.

Insert asks for Table and Columns, a comma-separated list of properties carrying the exact target column names; the node builds a single INSERT INTO ... VALUES and hands it every item as an array of binds. Update asks for Table, Columns and Update Key (id by default), the property identifying the row — but it runs one UPDATE per input item. A hundred items, a hundred statements.

The node also rejects the PUT and GET SQL commands: Local file access isn't allowed. So no local file can reach an internal stage from n8n — you need an external stage (S3, GCS, Azure).

Cost: the rule that matters

Benoit Dageville, Thierry Cruanes, Marcin Zukowski and their co-authors describe in "The Snowflake Elastic Data Warehouse", published at SIGMOD 2016 (see on Google Scholar), the strict separation between shared persistent storage and ephemeral compute clusters, the virtual warehouses. You therefore do not pay for the rows you read, you pay for the time the warehouse is running — the mental flip to make compared with Postgres or SQL Server, where a small query against an already-provisioned server is free.

Three settings then cover the reasoning: AUTO_SUSPEND defaults to 600 seconds when a warehouse is created, billing is per second with a 60-second minimum on every start, and an X-Small burns 1 credit per hour (each larger size doubles that).

The trap adds up quickly. A Schedule Trigger every minute: the warehouse never suspends, 24 credits a day for a few milliseconds of useful work. Every five minutes with AUTO_SUSPEND = 60: 288 wake-ups, each billed at the 60-second minimum, which is 4.8 hours of compute per day.

Measurement confirms the imbalance. Midhul Vuppalapati, Justin Miron, Rachit Agarwal, Dan Truong, Ashish Motivala and Thierry Cruanes analyse in "Building An Elastic Query Engine on Disaggregated Storage" (NSDI 2020 — see on Google Scholar) some 70 million Snowflake queries over fourteen days: the load is extremely irregular — for close to 30% of virtual warehouses, the standard deviation of CPU usage over time is as large as its own mean, and requirements can swing by an order of magnitude within a single hour. In workflow-style usage, the dominant cost is never compute, it is uptime.

Hence three rules: space out the Schedule Trigger; group your questions into one query rather than scattering five workflows; and let Snowflake aggregate, because a GROUP BY returning 40 rows is cheaper, in compute and in n8n memory alike, than 400,000 rows pulled in and aggregated inside the workflow.

Bulk loading: the real anti-pattern

A columnar warehouse is not a transactional database. Daniel Abadi, Peter Boncz, Stavros Harizopoulos, Stratos Idreos and Samuel Madden lay out the principle in "The Design and Implementation of Modern Column-Oriented Database Systems" (2012, Foundations and Trends in Databasessee on Google Scholar): columnar storage, compression and late materialisation optimise analytical scans, at the cost of expensive single-row writes. On Snowflake, every write rewrites immutable micro-partitions — an Update over a thousand items is simply the wrong tool.

Three alternatives by volume: up to a few thousand rows, the Insert operation, which already groups its binds; beyond that, a CSV or Parquet file dropped on an external stage followed by a COPY INTO; for recurring incremental updates, a staging table then a single MERGE. And if what you need is a continuous stream from a known source, the answer is not n8n but your existing ELT layer — a BigQuery warehouse poses the same trade-off.

The REST SQL API through HTTP Request

The native node runs a query and waits for the result. For what it does not cover — a long query, a COPY INTO you would rather not wait on, execution tracking — the REST SQL API drives nicely from an HTTP Request node. A POST to /api/v2/statements submits a statement; if it runs longer than 45 seconds, or if you pass async=true, Snowflake answers HTTP 202 with a statementHandle and a statementStatusUrl, and the result is fetched with a GET on the same endpoint suffixed with the handle.

{
  "statement": "COPY INTO sales FROM @my_stage/2026/08/ FILE_FORMAT = (TYPE = CSV)",
  "warehouse": "WH_LOAD",
  "role": "ROLE_ETL",
  "timeout": 600
}

The timeout field caps the wait; without it, the session's STATEMENT_TIMEOUT_IN_SECONDS parameter applies. Submit, then poll the status, with an Error Workflow to catch failures rather than discover them in an empty report.

Five use cases that justify n8n

  • Daily report: Schedule Trigger at 7 am, one aggregated query, delivery to Google Sheets or as a formatted Slack message. The warehouse runs for one minute a day. For an actual dashboard, let Power BI connect to Snowflake directly instead.
  • Anomaly detection: a query compares today's revenue against the average of the previous four weeks, an If node decides, an alert goes out. Same logic for a stalled data pipeline — a MAX(loaded_at) older than six hours fires the notification.
  • Enrichment from an API with no connector: a niche business tool, an internal scoring service, a public reference dataset. n8n calls, normalises and loads into a staging table — precisely the ground Fivetran does not cover.
  • Marketing segment export: a query isolates churn-risk customers, n8n pushes them to the CRM or the emailing platform. Snowflake computes, n8n distributes.
  • Natural-language questions: an LLM turns the question into SQL and the node runs it. The guardrails are not optional — a read-only role, an enforced LIMIT, an allowlist of views. The principles described for querying a database in natural language all apply, with an extra financial stake: an unfiltered generated query scans terabytes fast.

The traps

  • Identifier case: Snowflake stores every unquoted identifier in UPPERCASE, and the node applies the same normalisation to the Table and Columns fields. A table created as "MyTable" must be typed with its quotes, otherwise the node will look for "MYTABLE".
  • A role without rights: without USAGE on the schema, the role sees no tables, and the error looks exactly like a missing table.
  • Volume pulled into n8n: a SELECT * on a warehouse table blows up worker memory. Aggregate in SQL; if the result really must come out in bulk, write a file rather than items, which is what binary data handling exists for.
  • Timestamps: TIMESTAMP_NTZ carries no zone, TIMESTAMP_LTZ renders in the session's zone, TIMESTAMP_TZ carries its own. A "today" report computed on a UTC warehouse but triggered in Europe/Paris drifts by one or two hours.
  • The warehouse that never shuts down: the suspension process runs roughly every 30 seconds, so setting AUTO_SUSPEND below that buys nothing. Watch WAREHOUSE_METERING_HISTORY in SNOWFLAKE.ACCOUNT_USAGE: that is where chatty workflows show up.
  • An over-powered service account: one role for reading, another for writing, never the same credential for both.

Key takeaways

n8n around Snowflake is orchestration, not ETL. The node covers three operations — Execute Query with its Query Parameters, a grouped Insert, a row-by-row Update — and the credential comes down to a session context (Account, Database, Schema, Warehouse, Role) plus password or key-pair authentication. The rest is one discipline: the warehouse costs uptime, not rows read.

Going further

If your Snowflake queries exist to answer business questions phrased in plain language, the RAG Assistant Pack (€119) shows how to frame a model with controlled context and verifiable sources, rather than letting it improvise SQL. And because read access to the central warehouse is as much a governance matter as a technical one, the Compliance & Audit Pack (€149) provides the timestamped audit trail documenting which workflow queried which data, and when.

FAQ

Frequently asked questions

Can n8n replace Fivetran or dbt for loading Snowflake?

No, and you should not try. Fivetran industrialises replication from known sources (CDC, schema drift, incident recovery) and dbt handles dependencies, tests and documentation for SQL transformations. n8n has no dependency graph, no schema management and no data tests. Its value lies elsewhere: orchestrating the last mile around the warehouse — triggering a query, pushing the result to a team, reacting to an anomaly, feeding a table from a business API no connector covers.

Why is my n8n workflow inflating my Snowflake bill?

Because Snowflake bills the time the virtual warehouse is running, not the number of rows read. AUTO_SUSPEND defaults to 600 seconds: a Schedule Trigger that queries Snowflake every minute mechanically prevents suspension and keeps the warehouse up 24 hours a day, which is 24 credits per day on an X-Small. Add per-second billing with a 60-second minimum on every start: 288 daily wake-ups cost nearly five hours of compute for a few seconds of actual querying.

How do I avoid SQL injection in the n8n Snowflake node?

Never drop an n8n expression straight into the query text. Use the Query Parameters field in the Options section of the Execute Query operation: it takes a comma-separated list of values, which you then reference with positional placeholders in the SQL. Values are handed to the Snowflake driver as bound parameters, never concatenated into the string. Check the hint shown under the field in your own instance, as the placeholder syntax has shifted between node versions.

Why can the Snowflake node not find my table when it clearly exists?

Three causes, in this order. First, case: Snowflake stores every unquoted identifier in UPPERCASE, and the node applies the same rule to the Table and Columns fields, so a table created with quotes in mixed case must be typed with its quotes. Second, the role: the credential's Role field decides what the session may do, and a role without USAGE on the schema sees nothing. Third, context: the credential's Database and Schema fields set the starting point, so a table in another schema needs a fully qualified name.

Bundle FlowKit Complet

€269