Domain 1.5 β Snowflake Storage Concepts
Master micro-partitions, data clustering, Time Travel, Fail-Safe, Zero-Copy Cloning, and all Snowflake table and view types. Understand how Snowflake stores and protects your data.
Domain 1.5 β Snowflake Storage Concepts
Exam Weight
Domain 1.0 accounts for ~31% of the exam. Storage concepts are foundational and appear in performance, governance, and data loading domains too.
This lesson maps to Exam Objective 1.5: Explain Snowflake storage concepts, including micro-partitions, data clustering, and all table and view types.
Micro-Partitions
Micro-partitions are the fundamental storage unit in Snowflake. Every table's data is divided into micro-partitions automatically β no manual partitioning required.
Key Characteristics
| Property | Value |
|---|---|
| Size | 50β500 MB (compressed) |
| Format | Columnar (column-oriented) |
| Compression | Automatic (Snowflake chooses algorithm) |
| Encryption | AES-256, automatic |
| Immutability | Immutable β DML creates new partitions |
| Metadata | Min/max values, distinct count, NULL count per column per partition |
Columnar Storage
Snowflake stores data by column, not by row. This has major performance implications:
Benefits for analytics:
- Only the queried columns are read from disk β less I/O
- Similar values in a column compress extremely well β smaller storage
- Aggregate queries on one column skip all other columns
Partition Pruning
Because Snowflake stores min/max metadata per column per micro-partition, it can skip entire partitions that don't match a WHERE clause:
-- Snowflake's optimizer knows which micro-partitions contain
-- orders from January 2025 and skips all others
SELECT sum(amount)
FROM orders
WHERE order_date BETWEEN '2025-01-01' AND '2025-01-31';This is called partition pruning and is critical for query performance.
Data Clustering
Natural Clustering
When data is loaded in a consistent order (e.g., chronologically by created_at), micro-partitions are naturally well-clustered β queries filtering on that column benefit from pruning.
Cluster Keys
For tables where the natural load order doesn't match query patterns, you can define an explicit Cluster Key:
-- Define a cluster key on the region and event_type columns
ALTER TABLE events CLUSTER BY (region, event_type);
-- Check clustering quality (0 = perfectly clustered, 1 = no clustering)
SELECT SYSTEM$CLUSTERING_INFORMATION('events', '(region, event_type)');Automatic Clustering
When a cluster key is defined, Snowflake's Automatic Clustering service runs in the background to re-organize micro-partitions β this consumes credits on your behalf.
| Concept | Description |
|---|---|
| Cluster Depth | Average number of overlapping partitions per value β lower is better |
| Clustering Ratio | Fraction of columns that are sorted within partitions β higher is better |
| Automatic Clustering | Background service that maintains clustering; billed separately |
Defining a cluster key on a small or infrequently queried table is wasteful β Automatic Clustering costs credits. Only cluster large tables (hundreds of GBs+) that are frequently queried on the cluster key column(s).
Time Travel
Time Travel allows you to query historical versions of your data β up to 90 days in the past (depending on edition):
| Edition | Max Time Travel |
|---|---|
| Standard | 1 day (24 hours) |
| Enterprise | Up to 90 days |
| Business Critical | Up to 90 days |
| VPS | Up to 90 days |
-- Query data as it was 1 hour ago
SELECT * FROM orders AT (OFFSET => -3600);
-- Query data at a specific timestamp
SELECT * FROM orders AT (TIMESTAMP => '2025-06-01 12:00:00'::TIMESTAMP_TZ);
-- Query using a query ID (before that query ran)
SELECT * FROM orders BEFORE (STATEMENT => '019f18ba-0804-0...');
-- Restore a dropped table
UNDROP TABLE orders;
-- Clone a table at a point in time
CREATE TABLE orders_backup CLONE orders
AT (TIMESTAMP => '2025-06-01 00:00:00'::TIMESTAMP_TZ);Time Travel Configuration
-- Set Time Travel retention for a specific table
ALTER TABLE orders SET DATA_RETENTION_TIME_IN_DAYS = 30;
-- Set at schema or database level
ALTER DATABASE my_db SET DATA_RETENTION_TIME_IN_DAYS = 7;
-- Disable Time Travel (reduce storage cost)
ALTER TABLE staging_table SET DATA_RETENTION_TIME_IN_DAYS = 0;Time Travel data does count toward storage billing. Setting retention to 0 for tables that don't need historical recovery is a cost optimization strategy.
Fail-Safe
Fail-Safe is a 7-day non-configurable disaster recovery window that begins after the Time Travel period expires.
Critical exam facts about Fail-Safe:
| Property | Value |
|---|---|
| Duration | Always 7 days (non-configurable) |
| Who can recover data | Snowflake Support only (not the customer) |
| Cost | Included in storage β no extra charge |
| Self-service? | No β contact support |
| Applies to | Permanent tables only (not Temporary or Transient) |
Fail-Safe is not a self-service recovery tool. If you need self-service point-in-time recovery, use Time Travel (UNDROP / AT / BEFORE). Fail-Safe is a last resort that requires Snowflake Support involvement.
Zero-Copy Cloning
Zero-Copy Cloning creates an instant copy of a database, schema, or table without duplicating any underlying data:
-- Clone entire database instantly
CREATE DATABASE DEV_DB CLONE PROD_DB;
-- Clone a schema
CREATE SCHEMA dev.staging CLONE prod.staging;
-- Clone a table
CREATE TABLE orders_backup CLONE orders;
-- Clone at a point in time (using Time Travel)
CREATE TABLE orders_jan CLONE orders
AT (TIMESTAMP => '2025-01-31 23:59:59'::TIMESTAMP_TZ);How Zero-Copy Cloning Works
After cloning, the clone shares the same micro-partitions as the source. When either the source or the clone is modified, Copy-on-Write creates new micro-partitions for the modified data only:
Initial state: [Partition A] [Partition B] [Partition C]
β β β
SOURCE SOURCE + CLONE SOURCE + CLONE
After UPDATE to clone:
Clone: [New Partition A'] [Partition B] [Partition C]
Source: [Partition A] [Partition B] [Partition C]
Benefits:
- Instant β no data is copied
- No extra storage cost initially
- Storage only increases when data diverges between source and clone
- Perfect for dev/test environments, pre-migration snapshots, auditing
Table Types (Comprehensive Review)
| Type | Persistence | Time Travel | Fail-Safe | Use Case |
|---|---|---|---|---|
| Permanent | Until dropped | 0β90 days | 7 days | Production tables |
| Temporary | Session end | 0β1 day | None | Session-scoped work |
| Transient | Until dropped | 0β1 day | None | Staging, intermediate ETL |
| External | Never (no data) | None | None | Query files in cloud storage |
| Apache Iceberg | Until dropped | Via Iceberg | Via Iceberg | Open format, multi-engine |
| Dynamic | Until dropped | Configurable | Configurable | Declarative incremental |
Apache Iceberg Tables
Snowflake supports Apache Iceberg as an open table format β data lives in your own cloud storage and is accessible by multiple engines (Spark, Trino, Snowflake):
-- Iceberg table using Snowflake as catalog
CREATE ICEBERG TABLE icebergtable (id NUMBER, name STRING)
CATALOG = SNOWFLAKE
EXTERNAL_VOLUME = 'my_external_volume'
BASE_LOCATION = 'iceberg_data/';Dynamic Tables
Dynamic Tables provide declarative incremental materialization β define the query result you want, and Snowflake keeps it fresh automatically:
CREATE DYNAMIC TABLE customer_summary
TARGET_LAG = '1 hour' -- data should be no older than 1 hour
WAREHOUSE = WH_TRANSFORM
AS
SELECT
customer_id,
count(*) as order_count,
sum(amount) as total_spent
FROM orders
GROUP BY customer_id;Dynamic Tables vs. Streams + Tasks:
- Dynamic Tables: simpler declarative approach β Snowflake manages the refresh logic
- Streams + Tasks: imperative β you write the merge/insert logic explicitly
View Types (Comprehensive Review)
| View Type | Definition Hidden | Pre-Computed | Auto-Refresh | Notes |
|---|---|---|---|---|
| Standard | No | No | N/A | Simple logical wrapper |
| Secure | Yes | No | N/A | Hides query logic from consumers |
| Materialized | No | Yes | Yes (background) | Performance optimization |
-- Materialized view: Snowflake refreshes this automatically
CREATE MATERIALIZED VIEW mv_hourly_sales AS
SELECT
date_trunc('hour', sale_time) AS sale_hour,
sum(amount) AS total_amount
FROM sales
GROUP BY 1;
-- Query the MV (reads pre-computed result)
SELECT * FROM mv_hourly_sales WHERE sale_hour > DATEADD('hour', -24, CURRENT_TIMESTAMP);Materialized View limitations:
- Cannot reference other MVs or external tables
- Cannot use non-deterministic functions
- Maintained by Snowflake's background service (consumes credits)
- Only available on Enterprise+
Encryption at Rest and in Transit
All Snowflake data is encrypted by default β no configuration required:
| Protection | Method |
|---|---|
| Data at rest | AES-256 (all micro-partitions) |
| Data in transit | TLS 1.2+ (all connections) |
| Key management | Snowflake-managed by default |
| Tri-Secret Secure | Customer-managed key (Business Critical+) |
Practice Questions
Q1. What is the size range of a Snowflake micro-partition?
- A) 1β10 MB uncompressed
- B) 50β500 MB compressed β
- C) 1β5 GB uncompressed
- D) Fixed at 128 MB
Q2. After Time Travel expires, who can recover data during the Fail-Safe period?
- A) The customer using UNDROP
- B) The ACCOUNTADMIN role
- C) Snowflake Support only β
- D) No one β data is immediately purged
Q3. A data engineer clones a production table (CREATE TABLE dev CLONE prod). No modifications are made yet. How much additional storage does the clone consume?
- A) 100% of the original table size
- B) 50% of the original table size
- C) None β micro-partitions are shared β
- D) Only metadata storage
Q4. Which table type is appropriate for storing intermediate ETL results that do not need Fail-Safe but should persist beyond the current session?
- A) Temporary
- B) Transient β
- C) Permanent
- D) External
Q5. A Dynamic Table is configured with TARGET_LAG = '1 hour'. What does this mean?
- A) The table refreshes every hour at the top of the hour
- B) The data in the table should be no more than 1 hour behind the source β
- C) The table retains 1 hour of Time Travel
- D) The warehouse runs for 1 hour per refresh
Q6. Which Snowflake view type hides its underlying SELECT definition from users who have not been granted access by the owner?
- A) Materialized View
- B) Standard View
- C) Secure View β
- D) External View
Q7. Automatic Clustering is enabled on a table. Which statement is TRUE?
- A) Clustering runs on the customer's virtual warehouse
- B) Clustering is free and unlimited
- C) Clustering consumes credits on Snowflake's background service β
- D) Clustering requires the table to be recreated
Key Takeaways for Exam Day:
- Micro-partitions: 50β500 MB compressed, columnar, immutable, automatic metadata
- Fail-Safe: 7 days, non-configurable, Snowflake Support only
- Time Travel: Standard = 1 day max | Enterprise+ = 90 days max
- Zero-Copy Cloning: instant, no initial storage cost, Copy-on-Write for divergence
- Transient vs Temporary: both no Fail-Safe, but Transient persists past session end
- Dynamic Tables: declarative
TARGET_LAGβ simpler than Streams + Tasks