Before data can be loaded into Snowflake, it lands in a stage - a location that holds files on their way in or out. Every bulk load and unload in Snowflake runs through a stage, and understanding the two kinds, internal and external, is the difference between a loading pipeline that's simple and one that quietly costs more or breaks at scale. A stage is just a named pointer to where files live, plus the file-format and credential details Snowflake needs to read or write them.

Internal stages: Snowflake-managed

An internal stage stores files in storage Snowflake manages for you. There are three flavors, each with a purpose:

  • User stage (@~) - a personal staging area tied to each user, good for files only that user loads.
  • Table stage (@%table_name) - automatically attached to a table, convenient when files map to exactly one table.
  • Named internal stage (@my_stage) - a database object you create and grant access to, the most flexible and the usual choice for shared loading workflows.

You push local files into an internal stage with the PUT command, then load them into a table with COPY INTO. Snowflake handles the storage and encryption; you don't manage a bucket.

External stages: your cloud storage

An external stage points at a location in your own cloud storage - Amazon S3, Azure Blob Storage, or Google Cloud Storage. Instead of copying files into Snowflake first, you reference them where they already sit. You create the stage with the storage URL plus credentials (ideally a storage integration that uses a cloud IAM role rather than embedded keys), then run COPY INTO against it. External stages suit data that already lands in a data lake, large volumes you don't want to duplicate, and pipelines where another system writes the files.

Which to use

  • Internal - quick loads of local or generated files, no external bucket to manage, fully inside Snowflake's boundary.
  • External - data already in S3/Azure/GCS, large or shared datasets, and pipelines where files originate elsewhere.

External stages also underpin continuous loading: Snowpipe watches an external stage and loads new files automatically as they arrive, turning a manual COPY INTO into a near-real-time pipeline.

A typical load

The pattern is consistent. Define a file format (CSV, JSON, Parquet, with its delimiters and options). Create or choose a stage. Stage the files (PUT for internal; they're already there for external). Then COPY INTO target_table FROM @stage with the file format and any transformations. Getting the file format and stage right up front is what makes loading repeatable.

Frequently asked questions

What is the difference between internal and external stages? Internal stages store files in Snowflake-managed storage; external stages point at your own S3, Azure, or GCS storage where the files already live.

What is a storage integration? A Snowflake object that lets an external stage authenticate to cloud storage via an IAM role instead of embedding access keys - the recommended, more secure approach.

How do PUT and COPY INTO differ? PUT uploads local files into an internal stage; COPY INTO loads staged files (internal or external) into a table.