Warehouses
On this page, you will:
- Build the
snowflake_warehousemodule - Create shared warehouses for different workloads
- Configure auto-suspend and sizing for cost efficiency
Why Dedicated Warehouses?
Snowflake warehouses are virtual compute clusters that run your queries. Unlike traditional databases where compute is tied to storage, Snowflake lets you create multiple warehouses that all access the same data.
Dedicated warehouses for different workloads provide:
- Cost tracking: See exactly how much each workload costs
- Resource isolation: Heavy transformations don't slow down reports
- Right-sizing: Size each warehouse for its specific workload
- Independent scaling: Scale up reporting without affecting loading
The Warehouse Module
Navigate to your Snowflake Terraform directory and create the warehouse module:
cd ~/projects/data/data-stack-infrastructure/terraform/snowflake
mkdir -p modules/snowflake_warehouse
main.tf
Create modules/snowflake_warehouse/main.tf:
terraform {
required_providers {
snowflake = {
source = "Snowflake-Labs/snowflake"
version = "~> 0.99"
configuration_aliases = [snowflake.sys_admin, snowflake.security_admin]
}
}
}
# -----------------------------------------------------------------------------
# Warehouse
# -----------------------------------------------------------------------------
resource "snowflake_warehouse" "this" {
provider = snowflake.sys_admin
name = upper(var.warehouse_name)
comment = var.warehouse_comment
# Start suspended to avoid immediate costs
initially_suspended = true
# Size and scaling
warehouse_size = var.warehouse_size
min_cluster_count = var.warehouse_min_cluster_count == 1 ? null : var.warehouse_min_cluster_count
max_cluster_count = var.warehouse_max_cluster_count == 1 ? null : var.warehouse_max_cluster_count
scaling_policy = var.warehouse_max_cluster_count > 1 ? var.warehouse_scaling_policy : null
# Cost control
auto_suspend = var.warehouse_auto_suspend
auto_resume = true
# Query acceleration (Enterprise edition)
enable_query_acceleration = var.warehouse_enable_query_acceleration
query_acceleration_max_scale_factor = var.warehouse_enable_query_acceleration ? var.warehouse_query_acceleration_max_scale_factor : null
lifecycle {
ignore_changes = [
initially_suspended # Prevents imported warehouses from being toggled
]
}
}
# -----------------------------------------------------------------------------
# Grants
# -----------------------------------------------------------------------------
resource "snowflake_grant_privileges_to_account_role" "usage" {
provider = snowflake.security_admin
for_each = toset(var.warehouse_usage_roles)
privileges = ["MONITOR", "OPERATE", "USAGE"]
account_role_name = upper(each.value)
on_account_object {
object_type = "WAREHOUSE"
object_name = snowflake_warehouse.this.name
}
}
This module:
- Creates the warehouse using
sys_admin(SYSADMIN role) - Grants usage permissions using
security_admin(SECURITYADMIN role) - Starts warehouses suspended to avoid immediate charges
- Handles multi-cluster warehouse settings conditionally
variables.tf
Create modules/snowflake_warehouse/variables.tf:
variable "warehouse_name" {
description = "The name of the warehouse (will be uppercased)"
type = string
}
variable "warehouse_comment" {
description = "Description of the warehouse's purpose"
type = string
}
variable "warehouse_size" {
description = "The size of the warehouse"
type = string
default = "X-Small"
validation {
condition = contains([
"X-Small", "Small", "Medium", "Large", "X-Large",
"2X-Large", "3X-Large", "4X-Large", "5X-Large", "6X-Large"
], var.warehouse_size)
error_message = "Invalid warehouse size. Must be X-Small through 6X-Large."
}
}
variable "warehouse_auto_suspend" {
description = "Seconds of inactivity before auto-suspend (minimum 60)"
type = number
default = 60
validation {
condition = var.warehouse_auto_suspend >= 60
error_message = "Auto-suspend must be at least 60 seconds."
}
}
variable "warehouse_min_cluster_count" {
description = "Minimum clusters for multi-cluster warehouse (Enterprise edition)"
type = number
default = 1
validation {
condition = var.warehouse_min_cluster_count >= 1 && var.warehouse_min_cluster_count <= 10
error_message = "Cluster count must be between 1 and 10."
}
}
variable "warehouse_max_cluster_count" {
description = "Maximum clusters for multi-cluster warehouse (Enterprise edition)"
type = number
default = 1
validation {
condition = var.warehouse_max_cluster_count >= 1 && var.warehouse_max_cluster_count <= 10
error_message = "Cluster count must be between 1 and 10."
}
}
variable "warehouse_scaling_policy" {
description = "Scaling policy for multi-cluster warehouses: STANDARD or ECONOMY"
type = string
default = "STANDARD"
validation {
condition = contains(["STANDARD", "ECONOMY"], var.warehouse_scaling_policy)
error_message = "Scaling policy must be STANDARD or ECONOMY."
}
}
variable "warehouse_enable_query_acceleration" {
description = "Enable query acceleration (Enterprise edition)"
type = bool
default = false
}
variable "warehouse_query_acceleration_max_scale_factor" {
description = "Max scale factor for query acceleration (1-100)"
type = number
default = 8
validation {
condition = var.warehouse_query_acceleration_max_scale_factor >= 1 && var.warehouse_query_acceleration_max_scale_factor <= 100
error_message = "Query acceleration scale factor must be between 1 and 100."
}
}
variable "warehouse_usage_roles" {
description = "Account roles to grant USAGE, OPERATE, and MONITOR privileges"
type = list(string)
default = []
}
outputs.tf
Create modules/snowflake_warehouse/outputs.tf:
output "warehouse_name" {
description = "The name of the warehouse"
value = snowflake_warehouse.this.name
}
output "warehouse_size" {
description = "The size of the warehouse"
value = snowflake_warehouse.this.warehouse_size
}
Create Shared Warehouses
Now use the module to create warehouses for different workloads. Create warehouses.tf in your root Snowflake directory:
# =============================================================================
# Shared Warehouses
# =============================================================================
# Dedicated warehouses for different workload types.
# Each warehouse can be sized and configured independently.
# -----------------------------------------------------------------------------
# Loading Warehouse
# -----------------------------------------------------------------------------
# Used by data ingestion tools (Airbyte, dlt, Fivetran)
module "warehouse_loading" {
source = "./modules/snowflake_warehouse"
providers = {
snowflake.sys_admin = snowflake.sys_admin
snowflake.security_admin = snowflake.security_admin
}
warehouse_name = "LOADING"
warehouse_comment = "Data ingestion from external sources."
warehouse_size = "X-Small"
# Loaders run periodically, suspend quickly between loads
warehouse_auto_suspend = 60
warehouse_usage_roles = [
# Add loader service accounts here as you create them
# "SVC_AIRBYTE",
# "SVC_DLT",
]
}
# -----------------------------------------------------------------------------
# Transforming Warehouse
# -----------------------------------------------------------------------------
# Used by dbt for transformations
module "warehouse_transforming" {
source = "./modules/snowflake_warehouse"
providers = {
snowflake.sys_admin = snowflake.sys_admin
snowflake.security_admin = snowflake.security_admin
}
warehouse_name = "TRANSFORMING"
warehouse_comment = "dbt transformations and data modelling."
warehouse_size = "Small"
# Transformations run in bursts, suspend between runs
warehouse_auto_suspend = 60
warehouse_usage_roles = [
# Add transformer service accounts here
# "SVC_DBT",
]
}
# -----------------------------------------------------------------------------
# Reporting Warehouse
# -----------------------------------------------------------------------------
# Used by BI tools (Metabase, Looker, Tableau)
module "warehouse_reporting" {
source = "./modules/snowflake_warehouse"
providers = {
snowflake.sys_admin = snowflake.sys_admin
snowflake.security_admin = snowflake.security_admin
}
warehouse_name = "REPORTING"
warehouse_comment = "Business intelligence and reporting queries."
warehouse_size = "Small"
# BI tools have sporadic usage, but keep warm for responsiveness
warehouse_auto_suspend = 300
warehouse_usage_roles = [
# Add reporter roles here
# "ANALYTICS_REPORTER",
# "SVC_METABASE",
]
}
# -----------------------------------------------------------------------------
# Developer Warehouse
# -----------------------------------------------------------------------------
# Used by data team members for ad-hoc queries
module "warehouse_developer" {
source = "./modules/snowflake_warehouse"
providers = {
snowflake.sys_admin = snowflake.sys_admin
snowflake.security_admin = snowflake.security_admin
}
warehouse_name = "DEVELOPER"
warehouse_comment = "Ad-hoc queries and development work."
warehouse_size = "X-Small"
# Developers often pause between queries
warehouse_auto_suspend = 120
warehouse_usage_roles = [
# Add developer roles here
# "ANALYTICS_DEVELOPER",
]
}
Roles Coming Later
The warehouse_usage_roles are commented out because we haven't created the functional roles yet. You'll uncomment these in the Functional Roles section.
Warehouse Sizing Guide
Warehouse size affects both performance and cost. Each size doubles the compute power (and cost) of the previous:
| Size | Credits/Hour | Best For |
|---|---|---|
| X-Small | 1 | Development, light loads, testing |
| Small | 2 | Small datasets, basic transformations |
| Medium | 4 | Medium datasets, complex joins |
| Large | 8 | Large datasets, heavy aggregations |
| X-Large+ | 16+ | Very large datasets, intensive workloads |
Start Small, Scale Up
Always start with X-Small or Small. Monitor query performance and scale up only when queries are consistently slow. Snowflake makes it easy to resize without downtime.
Cost Control Settings
The module includes several cost control features:
Auto-Suspend
Warehouses automatically suspend after a period of inactivity:
warehouse_auto_suspend = 60 # Suspend after 60 seconds
- 60 seconds: Aggressive, best for batch workloads (loading, transforming)
- 300 seconds: Moderate, good for interactive use (reporting)
- 600+ seconds: Conservative, for very sporadic usage
Auto-Resume
Warehouses automatically resume when a query arrives:
auto_resume = true # Always enabled in our module
This is always enabled so queries don't fail when the warehouse is suspended.
Initially Suspended
New warehouses start in a suspended state:
initially_suspended = true
This prevents charges from accumulating immediately after creation.
Commit and Deploy
Commit your changes and push to trigger the CI/CD pipeline:
git add terraform/snowflake/
git commit -m "Add snowflake_warehouse module and shared warehouses"
git push
The pipeline will run terraform plan on the pull request. Review the plan to confirm it will create four warehouses:
Plan: 4 to add, 0 to change, 0 to destroy.
+ module.warehouse_developer.snowflake_warehouse.this
+ module.warehouse_loading.snowflake_warehouse.this
+ module.warehouse_reporting.snowflake_warehouse.this
+ module.warehouse_transforming.snowflake_warehouse.this
Once merged, the pipeline applies the changes automatically.
Verify in Snowflake
After the pipeline completes, connect to Snowflake and verify the warehouses were created:
SHOW WAREHOUSES;
You should see your four new warehouses, all initially suspended.
Summary
You've created the warehouse infrastructure for your data platform:
- Built the
snowflake_warehousemodule - Created LOADING, TRANSFORMING, REPORTING, and DEVELOPER warehouses
- Configured appropriate sizes and auto-suspend settings for cost efficiency
What's Next
With compute resources in place, you need somewhere to store data. In the next section, you'll create the snowflake_database module and set up databases with reader/writer roles.
Continue to Databases →