Apache Airflow Snowflake integration

Apache Airflow orchestrates Snowflake through the Snowflake provider package, so the schedule and dependencies live in Airflow while the heavy SQL and compute stay in Snowflake. This page covers the methods, setup sequence, credential placement and testing a team needs before go-live.

On this page

How an Apache Airflow Snowflake integration divides the work

A team running self-hosted Airflow that must trigger Snowflake loads, transformations or Snowpark jobs on a schedule needs to decide early which system owns which part of the work. The Snowflake provider package is the piece that connects the two. Airflow keeps the schedule, the dependency graph, retries, and the record of each run, while Snowflake runs the SQL, moves the staged files and executes the compute. Airflow workers mostly submit statements and wait for their results, so the heavy data work happens inside the Snowflake account rather than on your Airflow hosts.

This page covers the three operator families the topic is built around: the SQL API operators that send statements to Snowflake, the stage-copy operators that load files from a stage into tables, and the Snowpark and Snowpark container job operators that run Python workloads in Snowflake. Each family has different connection needs, different failure modes and different costs on the Snowflake side, so the choice is a design decision rather than a syntax choice. Exact operator and class names change between provider releases, so confirm each one against the Snowflake provider documentation for the Airflow version you run before you write DAG code.

Before you start, decide where each piece of logic belongs. Transformations that already exist as SQL should stay in Snowflake, and Airflow should only trigger them and check their outcome. Dependencies on files that arrive from outside should be modeled as explicit steps in the DAG, with a clear rule for what happens when a load is late or partially fails. Ask your integration partner or your own platform team to write down which team owns the Snowflake account, the warehouse sizing, the role grants and the credentials, because those answers decide who gets paged when a scheduled run fails at the Snowflake end.

What must be in place before the Snowflake provider is installed

The Snowflake provider sits on top of an Airflow installation, a Snowflake account and a network path between them. Gaps in any of the three tend to surface as failed connections or dependency errors after installation, so confirm each layer before writing the first DAG.

A supported Airflow 3 release

Start from a current Airflow 3 patch release on a Python version and metadata database listed in the prerequisites for that release. The current patch release at the time of writing is 3.3.2, which supports Python 3.10 to 3.14 and PostgreSQL 14 to 18 or MySQL 8.0, 8.4 and Innovation releases. Do not run the metadata database on SQLite or MariaDB, and confirm that the Airflow version you plan to run is still receiving fixes. Airflow 2 reached end of life on April 22, 2026, so a Snowflake integration built on it will need an upgrade first.

Snowflake account identifier

Record the account identifier and the region or cloud the account runs in before you create any Airflow connection. Confirm the exact format your Snowflake administrator uses, since connection fields depend on it. Also confirm which Snowflake endpoint your organization uses, because the same identifier can resolve differently across regions and private connectivity setups.

Dedicated service user

Create a service user for Airflow instead of reusing a person's account. Keep it non-interactive, name it for the pipeline platform, and set an owner who answers for its lifecycle. Ask your Snowflake administrator which authentication methods the account allows for service users, such as password, key pair or other options enabled in your account, and which of them your security policy accepts. The choice determines where secrets are stored in Airflow.

Least-privilege role and grants

Create a role for the Airflow service user that holds only the privileges its DAGs need on named databases, schemas, tables and stages. Separate read and write roles where pipelines differ, and avoid granting account-level or administrative roles. Document the grants as code or change tickets so that audit reviewers can trace who can do what. Revisit the role whenever a new DAG touches a new object.

Warehouse, database, schema and stage objects

List the virtual warehouse, databases, schemas and internal or external stages that the DAGs will reference, and create them before testing. Assign the warehouse size and auto-suspend settings with cost in mind, since compute is billed by the warehouse. Confirm the stage ownership and file formats used by copy operations, because a missing stage or format is a common cause of failed loads in early testing.

Network egress from workers and triggerer

Open outbound connectivity from every Airflow component that opens a Snowflake connection, which includes workers that run SQL tasks and the triggerer for deferrable waits. Test from those hosts, not from your laptop. If your organization routes egress through a proxy or uses private connectivity to Snowflake, document the path, the allowed hostnames and the certificate chain, and confirm the design with your network team before installation.

Pinned provider and constraints file

Install the Snowflake provider against the Airflow constraints file for your exact Airflow version, so that transitive dependencies such as the Snowflake connector stay within tested ranges. Pin the provider version in your build and record it alongside the Airflow image or virtual environment. Unpinned installs are a frequent source of dependency conflicts that appear only after a rebuild, so test the pinned set in staging first.

Choosing between the SQL API, stage copy and Snowpark job patterns

Use the SQL API pattern when a DAG needs to run statements, transformations, merges or data quality checks in Snowflake and wait for the result. The Airflow task is thin: it sends SQL to Snowflake, receives status and optionally rows, and decides the next step based on the outcome. Snowflake does all the data processing inside the virtual warehouse that the statement names. Because the work runs in Snowflake, the Airflow worker mostly waits, so the main design question is how long tasks hold a worker slot while a query runs.

  • Airflow task role: submits SQL text, polls or waits for completion, and passes small results to downstream tasks through XCom.
  • Snowflake role: parses, plans and executes the statement on the warehouse you name.
  • Warehouse cost drivers: warehouse size, how long each statement runs, and how many statements share one warehouse at the same time.
  • Concurrency: parallel DAG tasks that point at one warehouse queue against each other, so size and separate warehouses per workload deliberately.
  • Confirm in the provider docs: the exact operator names in the Snowflake provider, whether the operator supports deferrable mode, and which Snowflake features (such as key-pair authentication or query tags) the connection type accepts.

Before committing to this pattern, confirm the deferrable behavior and the connection options with the current provider documentation for your Airflow version.

Configuring the Snowflake connection in the right order

This sequence takes a self-hosted Airflow from no Snowflake access to a verified, least-privilege connection that runs a read-only query and then a controlled write path in a non-production environment. Each step closes with a check, so a failure is isolated before it reaches production data.

  1. Create a least-privilege Snowflake service user and role

    Your Snowflake administrator creates a dedicated service user and a role that grants only the warehouse usage, database, schema and table privileges the DAGs need. Keep read and write grants in separate roles so the first test can run without any write access. Done means the role is granted to the service user and a session opened as that user can see only the objects you intended, confirmed by running SHOW GRANTS TO ROLE on the role and checking the output against your access design.

  2. Install the Snowflake provider against Airflow constraints

    The platform team installs the Snowflake provider package into the same Python environment or container image as Airflow, using the constraints file that matches your Airflow 3 version so no other dependency shifts. Record the provider version in your image or requirements file. Done means the provider appears in the output of airflow providers list on the scheduler, worker and triggerer images, and each image reports the same version.

  3. Define the Snowflake connection with its context fields

    Create a connection of the Snowflake type in Airflow with the account identifier, warehouse, database, schema and role filled in. Use the account locator format your Snowflake organization uses, and confirm it with your administrator because account identifier formats vary. Leave secret material out of the form at this step. Done means the connection object lists all context fields with no blank values for the role and warehouse, which you can confirm in the connection editor or with airflow connections get.

  4. Store secret material in your chosen secrets backend

    Put the private key or password for the service user in your chosen secrets backend, such as a Vault or cloud secret manager, and reference it from the connection rather than typing it into the metadata database. Confirm the Airflow secrets backend configuration points at that store and that the connection is resolved from it. Done means the connection resolves its credentials at runtime from the backend, and a direct query of the Airflow connection table shows no password or private key values.

  5. Run a connection test from the Airflow UI

    Use the connection test action in the Airflow UI, or a short task that opens a hook session, to confirm Airflow can authenticate to the Snowflake account with the service user. Run it from the same network path the workers use, since egress rules often differ between the UI host and worker nodes. Done means the test returns a success message, and if it fails, the error text identifies whether the problem is authentication, network reachability or a missing role.

  6. Run one read-only statement from a test DAG

    Create a small test DAG in a non-production environment with a single SQL task that runs a read-only statement such as selecting the current role, warehouse and database. Trigger it manually and open the task log. Done means the task succeeds and the log shows the query returned the expected context values and a Snowflake query ID, which you can later match against the query history in Snowflake.

  7. Run a stage-copy or Snowpark task in non-production

    Run one controlled write path, either a copy from a named stage into a non-production table or a Snowpark job, using a test dataset with a known row count. Keep the write role separate from the read role. Done means the task log records the statement or job ID, the target table row count matches the expected count, and Snowflake query history shows the statement ran under the intended service role.

  8. Promote the connection pattern to production deliberately

    Repeat the same sequence in production with a separate service user, role and secret path, rather than copying the non-production secret. Record the verified provider version, connection fields and test results in your change record. Done means the production connection passes the same connection test and read-only check, and the change record links each check to its evidence, which supports later audit requests.

Mapping Airflow connection fields and roles to Snowflake objects

This table maps each Airflow connection field, task override and secret name to the Snowflake object or setting it controls, and names who should own each one. Read it when deciding which team sets each value and where it should be stored. Confirm exact field names in the Snowflake provider documentation before building connections.

Airflow itemSnowflake object or settingOwner
Connection ID (for example, snowflake_default or a named connection)Name Airflow tasks use to reference the account, role and warehouse settingsData platform engineering
Account identifier field in the connectionSnowflake account locator or organization and account identifier used to reach your accountSnowflake platform administrator
Warehouse field in the connectionDefault virtual warehouse that runs queries from DAG tasks, sized for scheduled workloadsSnowflake platform administrator
Database and schema fieldsDefault target database and schema for unqualified table references in SQL tasksData engineering team
Role field in the connectionSnowflake role the session assumes, granted only the privileges the pipeline needsSecurity or identity team, approved by data owners
Service user login in the connectionDedicated Snowflake service user for Airflow, with key-pair or other approved authenticationSecurity team, with the platform administrator creating the user
Stage used by copy operationsNamed internal or external stage that the stage-copy operators read from or write toData engineering team, with data owners approving paths
Task-level warehouse or role overridesPer-task settings that route heavy steps to a different warehouse or limit a task to a narrower roleDAG author, reviewed through code review
Airflow Variable or secret naming conventionStored secret names for account, user and key material, kept out of DAG code and the metadata databaseSecurity team sets the convention, platform team enforces it

Where Snowflake credentials should live in a self-hosted Airflow

Snowflake credentials should live in a secrets backend that your organization already operates, and Airflow should read them at task time through a connection ID. The Snowflake connection should not be written into DAG code, baked into environment variables inside a container image, or stored as plain Airflow Variables in the metadata database. Each of those placements copies the secret into places that are hard to inventory and hard to rotate. A DAG file is readable by everyone who can merge to the DAG repository, an image is readable by anyone who can pull it, and the metadata database is readable by anyone with database access and is included in every backup. Confirm which secrets backend your security team already runs, whether that is HashiCorp Vault, a cloud secrets manager or a Kubernetes-based store, and plan the Snowflake connection around it rather than around the Airflow default.

Limit who can read the connection at each layer. On the Airflow side, decide which components need the secret at all: the scheduler and DAG processor parse DAG files and do not normally open Snowflake connections, while the workers that execute Snowflake operators do. Restrict the secrets backend policy so that only the identity used by those workers can read the Snowflake path, and keep DAG authors on logical connection IDs without read access to the secret values themselves. Use one Snowflake service user per workload where practical, granted only the warehouse, database, schema and role that workload needs. Rotation then becomes an operational change: update the secret in the backend, let the next task pick it up, and retire the old key or password on the Snowflake side after a planned overlap. The DAGs should not change. Confirm with your Snowflake administrator which key-pair or password options your account policy allows for service users.

Decide between one shared Snowflake connection and one connection per team or environment before the first DAG is written, because changing it later means touching every operator. A shared connection is simpler to rotate and to document, but every DAG inherits the same privileges and the audit trail shows one identity for all pipeline activity. Separate connections per team or per environment, such as development, test and production, give clearer audit records and narrower blast radius, at the cost of more secrets to manage and more connection IDs to keep consistent. Note that the metadata database remains a copy target. Connections stored there, even encrypted, appear in database dumps, replicas and snapshots, so the backup set needs the same access controls, encryption and retention rules as the secrets backend, and restore procedures should be tested with that in mind.

Security controls for the Snowflake connection

Each card covers one control that governs how self-hosted Airflow authenticates to Snowflake, what it can reach, and how its activity is recorded. The controls work together: a narrow Snowflake role limits damage, network and secrets controls limit exposure, and audit and rotation show whether they still hold. Your security team should confirm the final settings against its own policies.

Least-privilege role per pipeline group

Create a separate Snowflake role for each pipeline group, with warehouse, database and schema grants limited to the objects that group reads or writes. A DAG that loads staging tables should not hold rights to finance marts. Review each role's grants for write access, ownership and any privilege that allows creating new users or roles. Ask who approves changes to these grants, since a single shared role makes every DAG author a administrator of the Snowflake account.

Network policy and egress from Airflow

Snowflake network policies can restrict which source IP ranges may open sessions, so only the Airflow workers, or the NAT addresses in front of them, can connect. Confirm the egress path from the worker subnet, including whether DNS and proxy rules let workers reach only the Snowflake account hostname. Review whether the Snowflake account is reachable from developer laptops or CI runners that also hold connection details. Your network team should document the allowed addresses and who can change them.

Secrets backend and access control in Airflow

Store the Snowflake connection in a secrets backend rather than the metadata database, so credentials are not visible to every user who can read connections in the Airflow UI. Limit which Airflow roles can create, edit or view connections, and confirm that DAG authors cannot read the secret values through task code. Check that the backend's own access policy matches the Airflow roles. The secrets backend and its access policy are a decision for your security team, and the Airflow security documentation describes the options.

Masking of connection values in logs

Airflow masks values of fields marked as sensitive in task logs, but masking depends on the field being recognized and the value appearing in exact form. Passwords, private keys and tokens can still leak when a DAG prints a query string, an exception message or a full connection extra field. Test a deliberately failing task and search its logs and the UI for the connection value. Ask who can read task logs, because log access is often broader than connection access.

Query history audit by application and user

Snowflake's query history records which user and role ran each statement, and you can tag sessions with a query tag so Airflow work is identifiable. Set a consistent tag per DAG or pipeline group, for example in the connection parameters, so reviewers can attribute queries to a team. Confirm who can read query history, how long it is retained in your account settings, and whether the records are exported to your log platform for review and investigation.

Password and key rotation procedure

Rotate the Snowflake credential on a schedule your policy sets, and rehearse the change in a non-production account first. Key-pair authentication lets you rotate keys with a new public key registered alongside the old one before the old key is removed. Document which systems hold the credential, who performs the change, and how a failed rotation is rolled back without stopping production schedules. Ask for evidence that revoked credentials no longer open sessions.

Common Snowflake integration failures and how to fix them

This table maps the failures teams most often hit when Airflow calls Snowflake, from connection tests to duplicate loads and dependency conflicts. Read each row as a first diagnostic step: check the symptom, confirm the likely cause in your own environment, then apply the first fix before escalating.

SymptomLikely causeFirst fix
Connection test fails with an account or host errorAccount identifier written in the wrong format, or the Airflow worker cannot reach the Snowflake endpoint over the networkConfirm the account identifier format in your Snowflake account settings, then test egress from the worker host to the Snowflake endpoint on port 443 through your proxy or firewall rules
Authentication errors after a working setup stops workingExpired or rotated key pair or token, a password changed in Snowflake, or the Airflow connection points at a different userCompare the login user in the Airflow connection with the service user in Snowflake, then rotate the key or secret in the connection store and rerun the connection test
Permission denied on schema, table or stageThe service role lacks usage on the database or schema, or write and read grants on the target stage or tableQuery the role's grants in Snowflake, add the missing USAGE, SELECT, INSERT or stage privileges to the role the connection uses, and confirm the connection's default role
Tasks sit in queue and never startThe virtual warehouse is suspended with no auto-resume, or it is saturated by concurrent queries from other workloadsCheck warehouse state and auto-resume settings, then limit Airflow pool slots for Snowflake tasks or give Airflow a dedicated warehouse so it does not compete with analysts
Duplicate rows after a task retryA non-idempotent INSERT or COPY ran once, reported failure after committing, and was retriedMake the load idempotent with MERGE on a business key, a truncate-and-reload into a staging table, or a load audit table checked before each run
DAG import or operator errors after an upgradeSnowflake provider version was not pinned, so a new release pulled in incompatible dependencies or changed operator behaviorPin the Snowflake provider and its dependencies with Airflow constraints for your Airflow version, rebuild the image, and run the DAGs in a staging environment before promotion

Questions teams ask before connecting Airflow to Snowflake

How much effort does an Airflow to Snowflake integration take?

Effort depends mostly on how many Snowflake objects, roles and pipelines the integration touches, not on the provider package itself. A small setup with one connection, a few SQL tasks and one stage-copy flow is far simpler than a platform with multiple warehouses, role hierarchies and Snowpark jobs. The main drivers are the number of Snowflake accounts and environments, how many DAGs call Snowflake, whether data moves through stages, and how credentials are issued and stored. Ask any partner to break the estimate down by these items so you can see where the time goes.

Can our own team build the Snowflake integration without outside help?

A team with working Airflow and Snowflake experience can usually build a basic integration in-house, provided it has time to learn the provider's connection model and test against a non-production account. Outside help tends to pay off when the team needs a reviewed credential design, production-grade DAG code, runbooks for failures, or a fixed scope with written acceptance tests. Be honest about who on your side owns Airflow upgrades, since the Airflow 3 upgrade path changes how task code reaches data systems.

What do we need from our Snowflake and Airflow administrators?

You need named owners on both sides before work starts. On the Snowflake side, that means someone who can create or review service users, roles, warehouses, network policies and stages for the pipeline. On the Airflow side, it means someone who controls the deployment, the metadata database, the secrets backend and the connection configuration. Confirm who approves changes to production roles, who can read connection secrets, and how environments are separated, because these decisions shape most of the access design.

How long does a typical Snowflake pilot take?

No general duration is set for this integration, so the answer depends on your environment. The main factors are how many pipelines are in the pilot, whether the Snowflake roles and network rules already exist, how quickly access approvals are granted, and whether your Airflow deployment is already running in production. A pilot limited to one or two representative pipelines goes faster than one that also proves secrets handling, monitoring and failure recovery. Ask for a timeline that lists these dependencies explicitly.

Do Snowpark jobs change the cost model for Airflow?

Yes, they can shift where cost sits, but the change depends on how the jobs run. When Airflow only submits SQL to Snowflake, compute is billed on Snowflake warehouses while Airflow workers stay light. Snowpark container jobs run work in Snowflake's infrastructure, so you should confirm how they are billed and whether the Airflow tasks wait on them using a worker slot or a deferrable pattern. Ask your partner to model warehouse runtime and Airflow worker time for your real schedule before you commit to a design.

How should Snowflake credentials be rotated?

Rotation should be handled in the secrets store, not by editing DAG code or connection text by hand. Use a dedicated service user per environment with the narrowest role that works, store its key pair or password in your secrets backend, and set a documented rotation schedule with a tested cutover step. Confirm that the team can rotate without a deployment, that old credentials are revoked after the cutover, and that rotation events are logged. The exact Snowflake mechanism for key rotation should be confirmed against current Snowflake documentation for your account type.

What should a fixed-scope quote for this integration contain?

A fixed-scope quote should name the Airflow version and deployment target, the Snowflake accounts and environments in scope, the operators and connection types to be built, and the pipelines included. It should list the security controls covered, such as credential storage and role design, along with the testing and handover deliverables. It should also state what is excluded, including upgrades and ongoing support, and which items are one-time and which recur. Written acceptance criteria and a named change process for scope additions protect both sides.

How DeployOpen scopes and delivers the Snowflake integration

DeployOpen plans, builds, documents and supports self-hosted Airflow that drives Snowflake from infrastructure you control. Engagements start with a written, fixed scope covering connections, credential storage, operators and handover, so you know what is delivered before work begins.

How we scope

  • Inventory the Snowflake workloads Airflow will trigger, including SQL API steps, stage copies and any Snowpark jobs.
  • Agree which Snowflake accounts, roles and warehouses each Airflow connection may use, with least-privilege grants.
  • Define where credentials live, such as a secrets backend, and record the scope in writing before work starts.

How we build

  • Configure the Snowflake provider connections and DAGs against your Airflow 3 deployment and your agreed secrets approach.
  • Build and test stage-copy and SQL steps in a non-production Snowflake environment before any production schedule is enabled.
  • Verify failure handling, retries and credential rotation paths with your team's own test runs before cutover.

How we hand over

  • Deliver the connection inventory, DAG source, configuration notes and a runbook for operating the Snowflake integration.
  • Walk your engineers through the build, the secrets layout and the steps for adding a new Snowflake connection.
  • Document open decisions and the items your team should confirm with Snowflake and in your own environment.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after handover.
  • Retainers can cover Airflow version upgrades and provider package updates that affect the Snowflake integration.
  • Ask for the support scope, response expectations and upgrade approach in writing alongside the initial quote.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.