Home Database External Tables & Iceberg: Multi-Cloud Data Access
Advanced 3 min · July 17, 2026

External Tables & Iceberg: Multi-Cloud Data Access

Master Snowflake external tables with Iceberg format for multi-cloud data lakes.

N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Lessons pulled from things that broke in production.

Follow
Production
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
Before you start⏱ 15-20 min read
  • Basic SQL knowledge (SELECT, WHERE, GROUP BY).
  • Familiarity with Snowflake concepts (warehouses, stages, storage integrations).
  • Access to a cloud storage bucket (S3, Azure Blob, GCS) with Iceberg tables.
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • External tables let you query data stored outside Snowflake (e.g., S3, Azure Blob) without loading it.
  • Iceberg is an open table format that supports ACID transactions and schema evolution on object storage.
  • Snowflake's Iceberg integration allows you to create external tables on Iceberg tables, enabling multi-cloud access.
  • You can query Iceberg external tables using standard SQL, and Snowflake handles partitioning and metadata.
  • Best for sharing data across clouds or with other engines like Spark, Trino, or Athena.
✦ Definition~90s read
What is External Tables, Iceberg, and Multi-Cloud Data Access?

Snowflake external tables with Iceberg let you query data stored in open table format across multiple clouds using standard SQL.

Imagine you have a giant filing cabinet (data lake) in a cloud storage.
Plain-English First

Imagine you have a giant filing cabinet (data lake) in a cloud storage. Normally, you'd have to bring files into your office (Snowflake) to read them. External tables let you read files directly from the cabinet without moving them. Iceberg is like a smart index card system that keeps track of which files are part of which table, even if they're in different cabinets across different offices (clouds). Snowflake can read those index cards and give you the data as if it were in your own office.

In modern data architectures, data often resides in multi-cloud data lakes (AWS S3, Azure Blob, GCS). Snowflake's external tables allow you to query that data directly without loading it into Snowflake storage. With the rise of open table formats like Apache Iceberg, you can now combine the flexibility of Iceberg's ACID transactions and schema evolution with Snowflake's powerful query engine. This tutorial dives deep into creating and querying Snowflake external tables on Iceberg tables, covering multi-cloud access patterns, production debugging, and best practices. You'll learn how to set up external tables, handle partitioning, and avoid common pitfalls. By the end, you'll be able to build a cross-cloud data lake that can be queried by Snowflake, Spark, Trino, and more.

What are External Tables in Snowflake?

External tables in Snowflake allow you to query data stored in external cloud storage (AWS S3, Azure Blob, GCS) as if it were a regular table. The data remains in the external location, and Snowflake reads it on the fly. This is useful for data lakes where you want to avoid data movement. External tables are read-only and support partitioning, file formats like Parquet, ORC, CSV, JSON, and now Apache Iceberg. They are defined using a storage integration and a file format. For Iceberg, Snowflake can read the Iceberg metadata to understand the table schema, partitions, and snapshots.

create_external_table.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- Create a storage integration (one-time setup)
CREATE STORAGE INTEGRATION my_s3_int
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'S3'
  ENABLED = TRUE
  STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/my-role'
  STORAGE_ALLOWED_LOCATIONS = ('s3://my-bucket/iceberg/');

-- Create external stage pointing to the Iceberg metadata location
CREATE STAGE my_iceberg_stage
  STORAGE_INTEGRATION = my_s3_int
  URL = 's3://my-bucket/iceberg/';

-- Create external table on Iceberg table
CREATE OR REPLACE EXTERNAL TABLE my_iceberg_ext_table
  WITH LOCATION = @my_iceberg_stage
  AUTO_REFRESH = FALSE
  FILE_FORMAT = (TYPE = PARQUET);

-- Note: For Iceberg, Snowflake reads the metadata from the stage location.
-- The Iceberg table must be written by an Iceberg-compatible engine (e.g., Spark, Flink).
Output
+----------------------------------+
| status |
|----------------------------------|
| External Table MY_ICEBERG_EXT_TABLE successfully created. |
+----------------------------------+
🔥Iceberg vs Parquet External Tables
📊 Production Insight
Always use AUTO_REFRESH = FALSE for external tables on Iceberg unless you have a catalog integration. Manually refresh after data changes.
🎯 Key Takeaway
External tables let you query data in place. Iceberg external tables automatically inherit schema and partitioning from the Iceberg metadata.

Setting Up an Iceberg Table in Snowflake

Snowflake can also create and manage Iceberg tables directly (Snowflake-managed Iceberg tables). This allows you to use Snowflake's compute to write Iceberg tables that can be read by other engines. To create an Iceberg table, you need an external volume (a storage location) and specify the Iceberg table format. Here's how to create a Snowflake-managed Iceberg table and then query it via an external table (or directly).

create_iceberg_table.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-- Create an external volume (requires ACCOUNTADMIN)
CREATE OR REPLACE EXTERNAL VOLUME my_iceberg_vol
  STORAGE_LOCATIONS = (
    (
      NAME = 'my-s3-location'
      STORAGE_PROVIDER = 'S3'
      STORAGE_BASE_URL = 's3://my-bucket/iceberg/'
      STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/my-role'
    )
  );

-- Create a Snowflake-managed Iceberg table
CREATE OR REPLACE ICEBERG TABLE my_iceberg_table (
  id INT,
  name STRING,
  dt DATE
)
  EXTERNAL_VOLUME = 'my_iceberg_vol'
  CATALOG = 'SNOWFLAKE'
  BASE_LOCATION = 'my_iceberg_table/';

-- Insert data (Snowflake writes Iceberg files)
INSERT INTO my_iceberg_table VALUES (1, 'Alice', '2025-01-01'), (2, 'Bob', '2025-01-02');

-- Query directly
SELECT * FROM my_iceberg_table;

-- Now create an external table on the same location (for cross-engine access)
CREATE OR REPLACE EXTERNAL TABLE my_iceberg_ext
  WITH LOCATION = @my_iceberg_stage
  FILE_FORMAT = (TYPE = PARQUET);

-- Note: The external table will see the same data as the managed table.
Output
+------+-------+------------+
| ID | NAME | DT |
|------+-------+------------|
| 1 | Alice | 2025-01-01 |
| 2 | Bob | 2025-01-02 |
+------+-------+------------+
💡Catalog Options
📊 Production Insight
When using Snowflake-managed Iceberg tables, the external volume must be set up with proper permissions. Test with a small dataset first.
🎯 Key Takeaway
Snowflake can both create and query Iceberg tables. Managed Iceberg tables are great for write-once, read-many scenarios across engines.

Multi-Cloud Data Access with Iceberg

One of the biggest advantages of Iceberg is that it is cloud-agnostic. You can have an Iceberg table stored in AWS S3, and query it from Snowflake running on Azure, or from Spark on GCP. Snowflake's external tables can read Iceberg tables from any cloud storage, as long as network access is configured. This enables multi-cloud data lakes. For example, you might have data produced in AWS, processed in Azure, and consumed in GCP. With Iceberg, all engines see the same consistent snapshot. To set up multi-cloud access, you need to create storage integrations for each cloud provider and point the external table to the Iceberg metadata location. Snowflake will read the metadata and data files from the remote cloud.

multi_cloud_query.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- Assume Iceberg table is in AWS S3, but Snowflake is on Azure
-- Create storage integration for AWS
CREATE STORAGE INTEGRATION aws_s3_int
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = 'S3'
  ENABLED = TRUE
  STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::...'
  STORAGE_ALLOWED_LOCATIONS = ('s3://my-bucket/iceberg/');

-- Create stage
CREATE STAGE aws_iceberg_stage
  STORAGE_INTEGRATION = aws_s3_int
  URL = 's3://my-bucket/iceberg/';

-- Create external table
CREATE EXTERNAL TABLE cross_cloud_table
  WITH LOCATION = @aws_iceberg_stage
  FILE_FORMAT = (TYPE = PARQUET);

-- Query across clouds
SELECT region, COUNT(*) FROM cross_cloud_table GROUP BY region;

-- If the Iceberg table uses a catalog (e.g., AWS Glue), you can integrate with Snowflake's Iceberg catalog integration.
Output
+--------+----------+
| REGION | COUNT(*) |
|--------+----------|
| US | 1500 |
| EU | 800 |
+--------+----------+
⚠ Network Costs
📊 Production Insight
For cross-cloud queries, monitor network latency. Use clustering or partitioning to minimize data scanned.
🎯 Key Takeaway
Iceberg external tables enable true multi-cloud data access. You can query data from any cloud provider using Snowflake's external table feature.

Partitioning and Clustering in Iceberg External Tables

Iceberg tables support partitioning (by a column, e.g., date) and clustering (sorting within partitions). Snowflake's external tables can leverage Iceberg's partition metadata to prune partitions during queries. This is critical for performance. When you create an external table on an Iceberg table, Snowflake reads the partition spec from the Iceberg metadata. You don't need to specify PARTITION BY in the external table definition. However, to get the best performance, ensure your queries filter on partition columns. You can also use clustering keys in the Iceberg table to further optimize scans.

partition_pruning.sqlSQL
1
2
3
4
5
6
7
8
9
10
-- Assume Iceberg table partitioned by dt (date)
-- Query with partition filter
SELECT * FROM my_iceberg_ext_table WHERE dt = '2025-01-01';

-- Check query profile to see partition pruning
EXPLAIN SELECT * FROM my_iceberg_ext_table WHERE dt = '2025-01-01';

-- Output will show "Partitions Pruned"
-- You can also see partition information
SHOW PARTITIONS IN EXTERNAL TABLE my_iceberg_ext_table;
Output
+-------------+--------------+------------+
| PARTITION | FILE_COUNT | ROW_COUNT |
|-------------+--------------+------------|
| dt=2025-01-01| 10 | 100000 |
| dt=2025-01-02| 12 | 120000 |
+-------------+--------------+------------+
💡Partition Evolution
📊 Production Insight
If you see full table scans, check that the partition column is correctly recognized. Use SHOW PARTITIONS to verify.
🎯 Key Takeaway
Partition pruning works automatically for Iceberg external tables. Always filter on partition columns for best performance.

Schema Evolution and Time Travel

Iceberg supports schema evolution: you can add, drop, or rename columns without rewriting data. Snowflake external tables on Iceberg automatically detect schema changes after a REFRESH. However, the external table definition must be updated if you want to query new columns. You can use ALTER EXTERNAL TABLE ... ADD COLUMN to add columns. Iceberg also supports time travel: you can query a specific snapshot ID or timestamp. Snowflake external tables do not directly support time travel; you need to use the Iceberg table's snapshot metadata. For Snowflake-managed Iceberg tables, you can use AT (TIMESTAMP => ...) syntax.

schema_evolution.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Add a new column to the Iceberg table (using Spark, for example)
-- ALTER TABLE my_iceberg_table ADD COLUMN email STRING;

-- In Snowflake, refresh the external table
ALTER EXTERNAL TABLE my_iceberg_ext_table REFRESH;

-- Add the column to the external table definition
ALTER EXTERNAL TABLE my_iceberg_ext_table ADD COLUMN email STRING;

-- Now query the new column
SELECT id, email FROM my_iceberg_ext_table;

-- For time travel on Snowflake-managed Iceberg table:
SELECT * FROM my_iceberg_table AT (TIMESTAMP => '2025-01-01 00:00:00'::TIMESTAMP);
Output
+------+-----------------+
| ID | EMAIL |
|------+-----------------|
| 1 | alice@example.com |
| 2 | bob@example.com |
+------+-----------------+
🔥Time Travel Limitations
📊 Production Insight
Always test schema changes in a non-production environment. Refresh the external table after schema changes.
🎯 Key Takeaway
Schema evolution is seamless with Iceberg external tables. For time travel, use managed Iceberg tables or the Iceberg catalog.

Performance Optimization and Best Practices

To get the best performance from Iceberg external tables, follow these practices: 1) Use partitioning and clustering in the Iceberg table. 2) Filter on partition columns. 3) Use column pruning (select only needed columns). 4) Consider materialized views if queries are repeated. 5) Monitor query profiles for full scans. 6) Use AUTO_REFRESH or scheduled tasks to keep metadata fresh. 7) For large tables, consider using Snowflake's search optimization service (not available for external tables yet). 8) Use the Iceberg REST catalog integration for better metadata management.

optimization.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
-- Create a materialized view on external table (if supported)
CREATE MATERIALIZED VIEW mv_iceberg AS
SELECT dt, COUNT(*) as cnt
FROM my_iceberg_ext_table
GROUP BY dt;

-- Query the materialized view
SELECT * FROM mv_iceberg WHERE dt = '2025-01-01';

-- Use clustering on the Iceberg table (if managed by Snowflake)
ALTER ICEBERG TABLE my_iceberg_table CLUSTER BY (dt);

-- For external tables, clustering is not applicable; rely on Iceberg partitioning.
Output
+------------+-----+
| DT | CNT |
|------------+-----|
| 2025-01-01 | 100 |
+------------+-----+
⚠ Materialized Views on External Tables
📊 Production Insight
If you notice slow queries, use the query profile to identify full scans. Consider converting to a Snowflake-managed Iceberg table for better performance.
🎯 Key Takeaway
Optimize Iceberg external tables by leveraging partitioning, column pruning, and materialized views. Monitor performance regularly.
● Production incidentPOST-MORTEMseverity: high

The Case of the Vanishing Partitions

Symptom
A scheduled query against an Iceberg external table returned no data for the latest partition, even though new files were present in S3.
Assumption
The developer assumed that Snowflake automatically refreshes the external table metadata on every query.
Root cause
Snowflake caches the Iceberg table's metadata (snapshot) for up to 24 hours by default. The new partition was added after the last metadata refresh.
Fix
Use ALTER EXTERNAL TABLE ... REFRESH to manually refresh the metadata, or set AUTO_REFRESH = TRUE (if using Snowflake-managed Iceberg tables). For external Iceberg tables, schedule a refresh using a task or use the Iceberg REST catalog integration.
Key lesson
  • External tables on Iceberg do not auto-refresh by default; you must refresh metadata to see new partitions.
  • Use Snowflake tasks to periodically refresh external tables in production.
  • Consider using Snowflake's Iceberg catalog integration for automatic metadata refresh.
  • Monitor query results for stale data; set up alerts when row counts drop unexpectedly.
  • Always test with a REFRESH after adding new data to the Iceberg table.
Production debug guideSymptom to Action4 entries
Symptom · 01
Query returns no rows for new partitions
Fix
Run ALTER EXTERNAL TABLE <name> REFRESH to update metadata.
Symptom · 02
Error 'File not found' or 'Access denied'
Fix
Check storage integration permissions and the file path in the Iceberg metadata.
Symptom · 03
Query slow on external table
Fix
Verify partitioning: Iceberg external tables benefit from partition pruning. Use clustering keys if needed.
Symptom · 04
Schema mismatch: column types differ
Fix
Iceberg supports schema evolution; ensure the external table definition matches the Iceberg schema. Use ALTER EXTERNAL TABLE ... ADD COLUMN if needed.
★ Quick Debug Cheat SheetOne-line description
No data in external table
Immediate action
Refresh metadata
Commands
ALTER EXTERNAL TABLE my_ext_table REFRESH;
SELECT COUNT(*) FROM my_ext_table;
Fix now
Schedule a task to refresh every 5 minutes.
Access denied to storage+
Immediate action
Check storage integration
Commands
DESC INTEGRATION my_storage_int;
LIST @my_stage;
Fix now
Grant necessary permissions on the cloud storage bucket.
Partition pruning not working+
Immediate action
Check partition columns
Commands
SHOW PARTITIONS IN EXTERNAL TABLE my_ext_table;
EXPLAIN SELECT * FROM my_ext_table WHERE dt='2025-01-01';
Fix now
Ensure the partition column is used in WHERE clause and matches the Iceberg partition spec.
FeatureSnowflake Regular TableSnowflake External Table (Parquet)Snowflake External Table (Iceberg)
Data StorageSnowflake internalExternal cloud storageExternal cloud storage
Schema EvolutionManual ALTERManual ALTERAutomatic via Iceberg metadata
PartitioningManual definitionManual definitionAutomatic from Iceberg spec
Time TravelYesNoNo (unless managed)
Write SupportYesNoNo (unless managed)
Multi-CloudNoYes (with storage integration)Yes
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
create_external_table.sqlCREATE STORAGE INTEGRATION my_s3_intWhat are External Tables in Snowflake?
create_iceberg_table.sqlCREATE OR REPLACE EXTERNAL VOLUME my_iceberg_volSetting Up an Iceberg Table in Snowflake
multi_cloud_query.sqlCREATE STORAGE INTEGRATION aws_s3_intMulti-Cloud Data Access with Iceberg
partition_pruning.sqlSELECT * FROM my_iceberg_ext_table WHERE dt = '2025-01-01';Partitioning and Clustering in Iceberg External Tables
schema_evolution.sqlALTER EXTERNAL TABLE my_iceberg_ext_table REFRESH;Schema Evolution and Time Travel
optimization.sqlCREATE MATERIALIZED VIEW mv_iceberg ASPerformance Optimization and Best Practices

Key takeaways

1
External tables on Iceberg allow querying data in place without loading into Snowflake.
2
Iceberg provides schema evolution, partitioning, and multi-cloud access.
3
Always refresh external tables after data changes to see new partitions.
4
Use partition pruning and column selection for optimal performance.
5
Snowflake-managed Iceberg tables offer write capabilities and time travel.

Common mistakes to avoid

3 patterns
×

Forgetting to refresh the external table after adding new data.

×

Assuming external tables support time travel.

×

Not using partition columns in WHERE clauses, causing full table scans.

INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the difference between a Snowflake external table and a regular ...
Q02SENIOR
How does Snowflake handle partitioning in Iceberg external tables?
Q03SENIOR
Explain how you would set up a multi-cloud Iceberg table that can be que...
Q01 of 03JUNIOR

What is the difference between a Snowflake external table and a regular table?

ANSWER
A regular table stores data in Snowflake's internal storage, while an external table references data stored outside Snowflake (e.g., S3). External tables are read-only and do not incur storage costs in Snowflake.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I write to an external table in Snowflake?
02
How do I refresh an external table automatically?
03
What file formats does Iceberg support?
04
Can I query Iceberg tables from multiple Snowflake accounts?
05
Is there a cost for using external tables?
N
Naren Founder & Principal Engineer

20+ years shipping high-throughput database systems. Lessons pulled from things that broke in production.

Follow
Verified
production tested
July 17, 2026
last updated
2,439
articles · all by Naren
🔥

That's Snowflake. Mark it forged?

3 min read · try the examples if you haven't

Previous
Cortex AI: Machine Learning, LLMs, and AI Workloads
21 / 33 · Snowflake
Next
Business Continuity: Replication, Failover, and Disaster Recovery