Back to Blog
Tutorial

Your First Snowflake Pipeline: CSV to Table, Time Travel Included

SkyTrainings TeamEditorial Team
1 September 2026
5 min read

A File Lands, Every Morning at 6 AM


A retail analytics team gets a fresh CSV export from their POS system dropped into cloud storage every morning before the store day starts. Someone needs that data sitting in a queryable table by 7 AM, joined against yesterday's inventory numbers, with no manual step in between. That daily handoff, plain files in, clean tables out, is what most people actually mean when they say "build a Snowflake pipeline." Not a diagram on a whiteboard. A repeatable path from a bucket to a table someone can run SQL against.


This walks through building that path for the first time: the three objects Snowflake needs, the load method to pick, and the point where beginners usually get surprised by something behaving differently than they expected.


The Three Things Every Pipeline Needs


Before any data moves, three objects have to exist. A virtual warehouse is the compute engine, the thing that actually reads and writes data; it's separate from storage, which is Snowflake's core architectural bet. A stage is a pointer to where the raw files live, whether that's an S3 bucket, Azure Blob, or a file uploaded directly into Snowflake. And a target table, structured to match what the source file actually contains, is where the data ends up. Get these three wrong, mismatched file format on the stage, undersized warehouse, a table schema that doesn't match the CSV header, and everything downstream breaks in ways that look like a data problem but are really a setup problem.


From raw files to a query-ready table
  1. 1

    Create a warehouse

    An X-Small is enough for a first pipeline; size up later if load times justify it

  2. 2

    Define a stage

    Point it at the cloud storage location holding the raw files, with a file format object matching the CSV/JSON structure

  3. 3

    Bulk load with COPY INTO

    Pull the historical backlog in one pass, so the table isn't empty on day one

  4. 4

    Set up Snowpipe

    Auto-ingest new files as they land, without a scheduled job checking on a timer

  5. 5

    Add a Stream and Task

    Capture what changed since the last run and transform it into the shape downstream queries expect

  6. 6

    Query the result

    The table is now something a dashboard or analyst can hit directly


Bulk Load or Snowpipe?


The retail team's morning file and Snowpipe's continuous ingestion look like they solve the same problem, but they don't, and picking wrong is the first mistake most people make.


Two ways data actually gets into Snowflake
01

COPY INTO (bulk load)

Best for backfilling history or a scheduled batch that only needs to run a few times a day

02

Snowpipe (continuous)

Best for files arriving unpredictably, ingested within seconds to minutes of landing, billed per file processed rather than per warehouse-hour


A once-daily 6 AM file doesn't need Snowpipe at all. A scheduled COPY INTO on a small warehouse handles it more cheaply, since Snowpipe's serverless compute is priced for irregular, high-frequency arrivals, not a single predictable batch. Reaching for the fancier option by default is a common early habit, and it's usually the wrong bill to pay.


When Someone Runs a Bad UPDATE


Every pipeline eventually has a bad day. Someone runs an UPDATE without a WHERE clause, or a transform job doubles a table's row count before anyone notices. This is where Snowflake's Time Travel actually earns its place in the course syllabus, not as a theoretical safety net but as the thing that turns a two-hour incident into a two-minute query.


Recovering from a bad write
Loading diagram…

Standard Edition keeps one day of Time Travel by default; Enterprise Edition can hold up to 90, per Snowflake's own documentation (docs.snowflake.com, 2026). After that window closes, Fail-safe kicks in for another seven days, but it isn't self-service. Only Snowflake support can pull data back at that stage, and it exists for disaster recovery, not routine "oops" moments. The practical lesson: don't lean on Fail-safe as a plan. Set a Time Travel retention that actually matches how often your team makes mistakes.


Watching the Bill


Warehouses bill per second, with a 60-second minimum every time one starts or resumes. That minimum matters more than it sounds: a warehouse that auto-suspends after 60 seconds of idle time and then gets pinged every two minutes by a chatty dashboard racks up dozens of those minimum charges in an afternoon. Auto-suspend set too aggressively can cost more than leaving a warehouse running slightly longer.


The other surprise is that doubling a warehouse's size doesn't double every query's speed. It roughly doubles compute for queries genuinely bottlenecked on parallelism, scanning and joining large tables, but a query already limited by a single slow join step or by result-set size won't finish meaningfully faster on a bigger warehouse. Sizing up fixes some slowness, not all of it.


Getting Hands-On


Reading through COPY INTO syntax and actually watching a Snowpipe ingest fire in real time are different experiences, and the second one is where the timing and cost behavior above stop being abstract. SkyTrainings' Snowflake course builds this exact sequence, warehouse and stage setup through Streams, Tasks, and cost management, against a real account rather than screenshots.


Start there. Explore the Snowflake Training course.

SnowflakeTutorialData EngineeringSnowpipeELT