Pro ยท Lesson 5 of 13

Stages, COPY, and Snowpipe

Files land on a stage. COPY turns files into table rows. Snowpipe does that continuously.

Sign in to save your place.

Picture it this way

A stage is the loading dock. A file format is the packing slip that says whether the boxes are CSV or Parquet. COPY INTO is the crew that unpacks the boxes into shelves. Snowpipe is a crew that starts when a new box arrives, instead of waiting for you to shout.

Stages and file formats

Internal stages live inside Snowflake: a user stage (@~), a table stage (@%table_name), or a named stage you create. External stages point at Amazon S3, Azure Blob Storage, or Google Cloud Storage that you manage.

File formats cover CSV and other delimited text, JSON, Avro, ORC, Parquet, and XML. Name the format once and reuse it in COPY, so a skipped header or a quote character is not retyped in every load.

A directory table on a stage lists the files themselves. That is the door into unstructured data, covered again in the Iceberg lesson. Enabling it does not by itself parse CSV into columns.

COPY INTO is the batch load

COPY INTO a table reads staged files with a running warehouse. ON_ERROR chooses whether one bad row aborts the file or is skipped. VALIDATION_MODE can preview errors without committing a load. After a successful load, Snowflake remembers which files it already loaded for that table, unless you tell COPY to force them.

Unloading is the reverse: COPY INTO @stage FROM table. Bulk unload to delimited files and JSON is on every edition.

CREATE OR REPLACE FILE FORMAT ff_csv
  TYPE = CSV
  SKIP_HEADER = 1
  FIELD_OPTIONALLY_ENCLOSED_BY = '"';

CREATE OR REPLACE STAGE stg_orders
  FILE_FORMAT = ff_csv;

COPY INTO orders
FROM @stg_orders
FILE_FORMAT = (FORMAT_NAME = ff_csv)
ON_ERROR = ABORT_STATEMENT;

Snowpipe and Snowpipe Streaming

Snowpipe is continuous micro-batch loading and is listed for every edition. A pipe wraps a COPY statement. AUTO_INGEST = TRUE waits for a notification from the storage cloud. The notification service is different on AWS, Azure, and Google Cloud, so follow the auto-ingest page for the cloud you chose. Snowpipe compute is serverless. It is not the same bill as LEARN_WH.

Snowpipe Streaming loads rows, not files. Snowflake's current overview describes a high-performance architecture and says the older classic architecture is planned for future deprecation. Use the high-performance path for new work. Elastic Channels are the recommended start: Snowflake manages channels, delivery is at-least-once, and order is not guaranteed. Named Channels are the ordered, exactly-once option and use offset tokens. The docs describe throughput up to 20 GB/s per table and ingest-to-query latency as low as about 5 seconds. Treat those as documented ceilings, not a promise for every account and region.

Fail-safe does not protect tables that contain data loaded by the classic streaming architecture. If you still have classic channels, read that limitation before you count on Fail-safe.

How a file becomes rows

A CSV in a bucket travels through a stage and a COPY command into a table.

  1. Cloud bucketorders_2026_10_01.csv
  2. StageA named place Snowflake can read
  3. COPY / SnowpipeParses files into rows
  4. Tableorders

Step 1 of 3A stage is a named location: an internal stage inside Snowflake, or an external stage pointing at your S3, Azure or Google Cloud bucket.

LIST @raw_stage;

Lab: format, stage, and a one-row load

This lab stays inside SQL. It creates a format and an internal stage, then loads a row you insert into a staged file using a COPY INTO from a SELECT, so you do not need a local file uploader. When you do have a CSV, upload it with SnowSQL PUT and point COPY at the stage.

USE WAREHOUSE LEARN_WH;
USE DATABASE LEARN_DB;
USE SCHEMA PUBLIC;

CREATE OR REPLACE FILE FORMAT ff_csv
  TYPE = CSV
  SKIP_HEADER = 1
  FIELD_OPTIONALLY_ENCLOSED_BY = '"';

CREATE OR REPLACE STAGE stg_orders
  FILE_FORMAT = ff_csv;

COPY INTO @stg_orders/orders.csv
FROM (SELECT 'order_id', 'region', 'amount'
      UNION ALL
      SELECT '4', 'west', '8')
FILE_FORMAT = (TYPE = CSV FIELD_OPTIONALLY_ENCLOSED_BY = '"')
OVERWRITE = TRUE;

CREATE OR REPLACE TABLE orders_loaded (
  order_id NUMBER,
  region STRING,
  amount NUMBER(10, 2)
);

COPY INTO orders_loaded
FROM @stg_orders/orders.csv
FILE_FORMAT = (FORMAT_NAME = ff_csv)
ON_ERROR = ABORT_STATEMENT;

SELECT * FROM orders_loaded;

Concept summary

Knowledge check

What does a file format object remember?

How is Snowpipe different from a COPY you run by hand?

Which streaming choice gives ordered, exactly-once delivery?

Official sources

Checked against Snowflake documentation in October 2026. Product behavior still depends on your edition, cloud, and region.