Manages a single Snowflake resource monitor (
snowflake_resource_monitor) — credit-quota, reset-schedule, and notify/suspend threshold policy — against thesnowflakedb/snowflakeprovider, pinned~> 2.17.
- ❄️ Manages a single
snowflake_resource_monitorobject — one keystone resource, no children, no cross-object grants. - 🔑 Encodes both of Snowflake's provider-enforced create-time pairing/rejection rules as
terraform validate-timevalidation {}blocks, so a malformed call fails before any API call rather than as an opaque error mid-apply. - 🧾 Emits
fully_qualified_nameas the safe cross-reference for attaching the monitor to a warehouse via the siblingterraform-snowflake-warehousemodule. ⚠️ Documents — but cannot validate offline — the lifecycle-level gotcha that unsetting every trigger on an existing monitor forces a destroy/recreate rather than an in-place update.
💡 Why it matters: an unbounded warehouse is an unbounded bill. A resource monitor is the only Snowflake-native guardrail that caps and alerts on credit spend per warehouse (or, outside this module's scope, per account) — modeling its create-time constraints as type-level validation means a malformed monitor definition never reaches a live Snowflake account in the first place.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- ⭐ Star this repository to help others discover this Terraform module.
- 🤝 Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- ☕ Buy me a coffee: buymeacoffee.com/microsoftexpert
Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!
flowchart LR
user["terraform-snowflake-user"]
thismod["terraform-snowflake-resource-monitor"]
keystone[["snowflake_resource_monitor.this"]]
warehouse["terraform-snowflake-warehouse"]
user -->|"fully_qualified_name feeds notify_users"| thismod
thismod -->|"creates"| keystone
keystone -->|"fully_qualified_name feeds resource_monitor_fully_qualified_name"| warehouse
style thismod fill:#29B5E8,color:#ffffff
style keystone fill:#11567F,color:#ffffff
style user fill:#ECEFF1,color:#000000
style warehouse fill:#ECEFF1,color:#000000
This module has a real sibling family, so the family DAG is not dropped: terraform-snowflake-user
feeds this module's notify_users input by reference (its fully_qualified_name output), and
this module in turn feeds terraform-snowflake-warehouse's
resource_monitor_fully_qualified_name input with its own fully_qualified_name output. Neither
sibling module is created or modified by this one — both relationships are consumed by
reference, per this library's composite/aggregation split (this library's "Composite modules"
convention).
flowchart TB
subgraph inputs["Inputs"]
name["name (required)"]
credit_quota["credit_quota"]
frequency["frequency + start_timestamp (paired)"]
end_timestamp["end_timestamp"]
notify_triggers["notify_triggers"]
suspend_trigger["suspend_trigger"]
suspend_immediate_trigger["suspend_immediate_trigger"]
notify_users["notify_users"]
end
keystone[["snowflake_resource_monitor.this"]]
subgraph outputs["Outputs"]
fqn["fully_qualified_name"]
outname["name"]
id["id"]
end
inputs -->|"renders"| keystone
keystone -->|"emits"| outputs
style keystone fill:#11567F,color:#ffffff
style inputs fill:#ECEFF1,color:#000000
style outputs fill:#ECEFF1,color:#000000
Resource inventory:
| Resource | Count | Notes |
|---|---|---|
snowflake_resource_monitor.this |
1 (keystone) | No for_each children — standalone module |
| Requirement | Value |
|---|---|
| Terraform | >= 1.12.0 |
snowflakedb/snowflake provider |
~> 2.17 |
| Provider block | Not present — the caller's root module configures the provider (account identifier, authentication) and passes any role alias in |
Schema notes that bite:
- No settable
commentargument. Unlike most modules in this library,snowflake_resource_monitordoes not expose an inputcommentargument — only a read-onlycommentfield nested inside the computedshow_outputblock (Snowflake'sSHOW RESOURCE MONITORSoutput). This module carries nocommentvariable — a deliberate, schema-verified deviation from this library's usual "comment is the universal tail" rule, not an oversight. frequency/start_timestamppairing is validate-time enforced. Set one, and you must set the other — this module rejects the mismatched case beforeterraform validateever calls the Snowflake API.- Triggers-only creation is validate-time rejected. Setting only
notify_triggers,suspend_trigger, and/orsuspend_immediate_triggerwith nothing else fails atterraform validate— Snowflake requires at least one ofcredit_quota,frequency,start_timestamp,end_timestamp, ornotify_usersalongside any trigger. ⚠️ Unsetting all triggers forces a recreate — live-apply-time only, not offline-validatable. Once at least one trigger has ever been applied, a later configuration that removes every trigger cannot be satisfied as an in-place update; the provider recreates the resource monitor instead.terraform validateonly ever sees one configuration in isolation, so this behavior is invisible until a realplan/applyagainst existing state.frequency/start_timestamphave no unset path. Removing either field from a caller's HCL does not clear the previously applied value on the Snowflake side — the provider preserves it, by its own documented design, rather than resetting to a default. Expect no corrective diff on the next plan after simply deleting the argument.- A nested
timeoutsblock exists on the schema but is not modeled here. The live schema exposes an optionaltimeouts { create, read, update, delete }block — Terraform's standard per-resource operation-timeout customization meta-argument, not a business-data field. This library's stance is that no Snowflake module exposes atimeoutsvariable, since the provider does not otherwise expose a configurable operation- timeout schema; this module follows that stance and does not surface it. - Case sensitivity.
nameis passed through as-is; Snowflake case-folds an unquoted identifier to upper case. This is a common source of "already exists" false negatives onimportif the caller assumes the name is stored verbatim.
CREATE RESOURCE MONITOR— the global, account-level privilege required to create the keystonesnowflake_resource_monitor.thisobject. In practice this typically requires the ACCOUNTADMIN role:CREATE RESOURCE MONITORis one of the few privileges Snowflake has historically reserved to ACCOUNTADMIN, and is only grantable to a custom role on accounts/ editions where Snowflake has enabled delegating it. Confirm the executing role's actual grant (via the caller's aliased provider configuration) before assuming a lesser-privileged role will succeed — a role without this privilege fails at apply time with a Snowflake authorization error, not atterraform validatetime.- Subsequent updates (
ALTER RESOURCE MONITOR) and drops require ownership of the object or an equivalent privileged role — normally satisfied automatically by whichever role's session created it.
- No specific Snowflake account edition requirement — resource monitors are available on every edition.
- No
preview_features_enabledflag required —snowflake_resource_monitoris documented by the provider as Stable (GA), not preview-gated. - The executing role must already hold
CREATE RESOURCE MONITOR(see above) — provisioned by the caller's root module/provider alias; this module cannot grant itself the privilege it needs to run. - If
notify_usersis populated, every referenced Snowflake user identifier must already exist in the account (typically created viaterraform-snowflake-user) before this module applies — this module does not create, look up, or validate the referenced users' existence. - If the monitor is meant to govern a warehouse's compute spend,
terraform-snowflake-warehousemust exist (or be applied in the same run) — attachment is that module's concern.
terraform-snowflake-resource-monitor/
├── providers.tf # required_providers + required_version — no provider {} block
├── variables.tf # name, credit_quota, frequency/start/end_timestamp, triggers, notify_users
├── main.tf # the keystone snowflake_resource_monitor.this — no children
├── outputs.tf # fully_qualified_name, name, id
├── README.md # this file
├── SCOPE.md # lightweight standalone spec — privileges, prerequisites, gotchas
└── examples/ # runnable example call sites
module "etl_budget_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_ETL_BUDGET"
credit_quota = 500
suspend_trigger = 100
}The caller's root module configures the snowflake provider (account identifier, authentication,
and any role alias — see this library's Authentication model convention). This module never declares
account_name, organization_name, user, role, or any credential-shaped variable.
Consumes:
| Input | Type | Source module |
|---|---|---|
notify_users (optional) |
set(string) |
terraform-snowflake-user's fully_qualified_name output, one entry per notified user — not a hard Terraform module dependency, just an accepted reference convention |
Emits:
| Output | Description | Consumed by |
|---|---|---|
fully_qualified_name |
Fully qualified identifier of the resource monitor | terraform-snowflake-warehouse's resource_monitor_fully_qualified_name input |
name |
Bare name of the resource monitor, as passed to var.name |
Documentation/display only |
id |
Terraform resource ID (the quoted identifier string used for terraform import) |
Documentation/display only |
1 · Minimal monitor (name only)
ℹ️ Matches the provider's own "minimal" example usage: without
credit_quotaor any trigger, the monitor is created but performs no work until attached and configured further.
module "placeholder_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_PLACEHOLDER"
}2 · Minimal monitor with only credit_quota set
💡
credit_quotaalone (no triggers) satisfies the "not triggers-only" rule trivially, since no trigger field is set at all — Snowflake tracks usage against the quota but takes no suspend action without a trigger.
module "reporting_quota_only" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_REPORTING_QUOTA_ONLY"
credit_quota = 250
}3 · Monthly monitor with start_timestamp = "IMMEDIATELY"
💡
frequencyandstart_timestampare set together, satisfying the pairing validation invariables.tf."IMMEDIATELY"is the provider-documented literal that resolves to the current date at apply time.
module "monthly_reset_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_MONTHLY_RESET"
credit_quota = 1000
frequency = "MONTHLY"
start_timestamp = "IMMEDIATELY"
suspend_trigger = 100
}4 · Daily monitor with explicit start and end timestamps
module "seasonal_daily_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_SEASONAL_DAILY"
credit_quota = 300
frequency = "DAILY"
start_timestamp = "2026-08-01 00:00"
end_timestamp = "2026-10-31 23:59"
suspend_trigger = 90
}5 · All three trigger types plus notify_users
🔑
notify_usersconsumesterraform-snowflake-user'sfully_qualified_nameoutput by reference — this module does not create or validate the referenced users.
module "finance_analyst" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-user.git?ref=v1.0.0"
name = "SVC_FINANCE_ANALYST"
}
module "data_platform_lead" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-user.git?ref=v1.0.0"
name = "SVC_DATA_PLATFORM_LEAD"
}
module "full_policy_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_FULL_POLICY"
credit_quota = 1000
frequency = "DAILY"
start_timestamp = "2030-12-07 00:00"
end_timestamp = "2035-12-07 00:00"
notify_triggers = [40, 50]
suspend_trigger = 50
suspend_immediate_trigger = 90
notify_users = [
module.finance_analyst.fully_qualified_name,
module.data_platform_lead.fully_qualified_name,
]
}6 · Notify-only thresholds (no suspend action)
💡
notify_triggersalone pluscredit_quotasends notifications at 60% and 80% but never suspends the assigned warehouse(s) — useful for a monitor that only wants visibility, not enforcement.
module "visibility_only_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_VISIBILITY_ONLY"
credit_quota = 400
notify_triggers = [60, 80]
notify_users = [module.finance_analyst.fully_qualified_name]
}7 · Suspend-only monitor (graceful suspend, no immediate cancel)
module "graceful_suspend_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_GRACEFUL_SUSPEND"
credit_quota = 600
suspend_trigger = 100
}8 · Suspend-immediate-only monitor
⚠️ suspend_immediate_triggercancels running queries outright with no grace period — reserve this for cost-critical, non-production warehouses where an interrupted query is preferable to overspend.
module "hard_stop_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_HARD_STOP"
credit_quota = 150
suspend_immediate_trigger = 100
}9 · YEARLY frequency with a real start_timestamp
module "annual_budget_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_ANNUAL_BUDGET"
credit_quota = 12000
frequency = "YEARLY"
start_timestamp = "2026-01-01 00:00"
suspend_trigger = 95
}10 · NEVER frequency (credit usage never resets)
ℹ️
frequency = "NEVER"still requires a pairedstart_timestampper the validation block —NEVERonly changes whether usage resets, not whether the pairing rule applies.
module "lifetime_quota_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_LIFETIME_QUOTA"
credit_quota = 50000
frequency = "NEVER"
start_timestamp = "IMMEDIATELY"
suspend_trigger = 100
}11 · WEEKLY frequency with a threshold over 100%
💡 The provider explicitly supports trigger values over 100 — useful for an early-warning notification well past nominal quota without suspending anything.
module "overage_alert_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_OVERAGE_ALERT"
credit_quota = 200
frequency = "WEEKLY"
start_timestamp = "IMMEDIATELY"
notify_triggers = [110, 150]
notify_users = [module.data_platform_lead.fully_qualified_name]
}12 · Multiple monitors at scale via a caller-level for_each
ℹ️ This module itself has no children (standalone), but a caller can still apply
for_eachat themoduleblock to stamp out one monitor per entry in a map — each instance is independently keyed, so adding or removing a team never disturbs its siblings.
variable "team_credit_quotas" {
type = map(number)
default = {
analytics = 300
ingestion = 500
reporting = 200
}
}
module "team_monitors" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
for_each = var.team_credit_quotas
name = "RM_TEAM_${upper(each.key)}"
credit_quota = each.value
suspend_trigger = 100
}13 · One monitor shared across two warehouses
module "shared_budget_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_SHARED_BUDGET"
credit_quota = 2000
suspend_trigger = 95
}
module "warehouse_etl" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-warehouse.git?ref=v1.0.0"
name = "WH_ETL"
resource_monitor_fully_qualified_name = module.shared_budget_monitor.fully_qualified_name
}
module "warehouse_reporting" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-warehouse.git?ref=v1.0.0"
name = "WH_REPORTING"
resource_monitor_fully_qualified_name = module.shared_budget_monitor.fully_qualified_name
}14 · ⚠️ Rejected shape — triggers set with nothing else
⚠️ This example is deliberately not runnable HCL. It illustrates the shapeterraform validaterejects — a validation failure is not something that can be shown as a working example, so this block is prose plus the invalid call, commented out.
Snowflake rejects a resource monitor created with only trigger fields
(notify_triggers/suspend_trigger/suspend_immediate_trigger) and nothing else:
# module "invalid_triggers_only" {
# source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
#
# name = "RM_INVALID_TRIGGERS_ONLY"
# suspend_trigger = 100 # no credit_quota, frequency, start_timestamp, end_timestamp, or
# # notify_users set alongside it
# }terraform validate fails this call site with:
Error: Invalid value for variable
on variables.tf line 158, in variable "suspend_trigger":
158: validation {
A resource monitor cannot be created with only trigger fields set (notify_triggers,
suspend_trigger, suspend_immediate_trigger). Set at least one of credit_quota, frequency,
start_timestamp, end_timestamp, or notify_users as well.
Adding any one of credit_quota, frequency (paired with start_timestamp), end_timestamp, or
notify_users resolves the error — see Example 7 for the minimal fix (adding credit_quota).
15 · 🏗️ End-to-end composition — user, monitor, and warehouse
Wires terraform-snowflake-user's fully_qualified_name output into this module's notify_users
input, and this module's fully_qualified_name output into terraform-snowflake-warehouse's
resource_monitor_fully_qualified_name input — the full cross-module contract shown in §4.
module "casey_finance_notify_user" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-user.git?ref=v1.0.0"
name = "SVC_casey_FINANCE_NOTIFY"
}
module "wh_etl_monitor" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-resource-monitor.git?ref=v1.0.0"
name = "RM_WH_ETL"
credit_quota = 1500
frequency = "MONTHLY"
start_timestamp = "IMMEDIATELY"
notify_triggers = [50, 75]
suspend_trigger = 90
suspend_immediate_trigger = 100
notify_users = [module.casey_finance_notify_user.fully_qualified_name]
}
module "wh_etl" {
source = "git::https://github.com/microsoftexpert/terraform-snowflake-warehouse.git?ref=v1.0.0"
name = "WH_ETL"
warehouse_size = "MEDIUM"
resource_monitor_fully_qualified_name = module.wh_etl_monitor.fully_qualified_name
}💡 The monitor and the warehouse are independently reusable:
module.wh_etl_monitorcould just as easily be attached to a second warehouse (see Example 13), andmodule.wh_etlcould just as easily reference a different monitor — attachment is deliberately not owned by either module.
| Variable | Type | Default | Required |
|---|---|---|---|
name |
string |
— | Yes |
credit_quota |
number |
null |
No |
frequency |
string |
null |
No |
start_timestamp |
string |
null |
No |
end_timestamp |
string |
null |
No |
notify_triggers |
set(number) |
[] |
No |
suspend_trigger |
number |
null |
No |
suspend_immediate_trigger |
number |
null |
No |
notify_users |
set(string) |
[] |
No |
Full variable schemas
variable "name" {
type = string
# Required. Unique within the account. Avoid `|`, `.`, `"` in the value. Passed through as-is —
# expect Snowflake to case-fold an unquoted name to upper case.
}
variable "credit_quota" {
type = number
default = null
# Credits allocated per frequency interval. A monitor with no credit_quota and no triggers
# performs no work.
}
variable "frequency" {
type = string
default = null
# One of: MONTHLY, DAILY, WEEKLY, YEARLY, NEVER.
# validation: must be one of the five values above, or null.
# validation: (frequency == null) == (start_timestamp == null) — must be set together.
}
variable "start_timestamp" {
type = string
default = null
# A real timestamp string, or the literal "IMMEDIATELY". Paired with frequency.
}
variable "end_timestamp" {
type = string
default = null
# A real timestamp string marking when the monitor suspends the assigned warehouse(s).
}
variable "notify_triggers" {
type = set(number)
default = []
# Percentage-of-credit_quota thresholds that send a notification only. Values over 100 allowed.
}
variable "suspend_trigger" {
type = number
default = null
# Percentage-of-credit_quota threshold that suspends the warehouse(s) gracefully.
# validation: rejects a call where only notify_triggers/suspend_trigger/
# suspend_immediate_trigger are set with none of credit_quota/frequency/start_timestamp/
# end_timestamp/notify_users also set.
}
variable "suspend_immediate_trigger" {
type = number
default = null
# Percentage-of-credit_quota threshold that suspends the warehouse(s) immediately, canceling
# running queries.
}
variable "notify_users" {
type = set(string)
default = []
# Set of Snowflake user identifiers (pass terraform-snowflake-user's fully_qualified_name output).
# Not validated for existence — an invalid reference fails at apply time.
}| Output | Description | Sensitive / Conditional |
|---|---|---|
fully_qualified_name |
Fully qualified identifier of the resource monitor — the safe cross-reference for sibling modules | Always present |
name |
Bare name of the resource monitor, as passed to var.name |
Always present |
id |
Terraform resource ID (import identifier) | Always present |
frequency/start_timestamppairing is enforced invariables.tf. The validation block onfrequencychecks(var.frequency == null) == (var.start_timestamp == null)— both null, or both set. This is a cross-variablevalidation {}block (Terraform 1.9+, well within this module's>= 1.12.0floor), so it fires regardless of which of the two variables a caller actually edited.- The "cannot create with only triggers set" rule is enforced in
variables.tf. The validation block onsuspend_triggerchecks that if any ofnotify_triggers,suspend_trigger, orsuspend_immediate_triggeris set, at least one ofcredit_quota,frequency,start_timestamp,end_timestamp, ornotify_usersis also set. It is intentionally a single validation block (not duplicated across all three trigger variables) to avoid redundant, identically-wordedterraform validateerrors for one underlying cause. ⚠️ Unsetting all triggers forces a recreate — a live-apply-time concern this module cannot validate offline. Once a monitor has ever had a trigger applied, Snowflake has no supported path to fully unset every trigger again; the provider's only way to reconcile a configuration that removes them all is to destroy and recreate the resource monitor.terraform validateevaluates one configuration in isolation and has no visibility into prior state, so this behavior only ever shows up in a realplan/applyagainst an existing monitor — flag it to reviewers before applying a change that removes every trigger from a monitor already in use.- Account-level assignment is out of scope. Assigning a resource monitor at the ACCOUNT level
(rather than per-warehouse) requires the ACCOUNTADMIN role and is not supported by the
snowflake_resource_monitorresource itself — the provider's own docs point callers atsnowflake_executeinstead. Neither this module norterraform-snowflake-warehousesupports account-level assignment; only warehouse-level assignment via the sibling warehouse module'sresource_monitor_fully_qualified_nameinput is supported in this library. - No
commentvariable. See the "Schema notes that bite" callout above — the resource itself has no settablecommentargument, so this module has none either, despite this library's usual universal-tail convention. notify_usersis a flatset(string), not a nested block. Confirmed against the live provider schema during Phase 1 grounding — nodynamicblock is needed inmain.tfto render it ornotify_triggers.
| Concern | Secure default in this module | Opt-out (caller must be explicit) |
|---|---|---|
| Object comment | N/A — the resource has no settable comment argument (schema-verified deviation from the house universal tail) |
Not applicable |
| Credit quota | null (unset) — the empty call creates a monitor that tracks nothing and takes no action |
Caller sets credit_quota explicitly |
Reset schedule (frequency/start_timestamp) |
Both null (unset) — no forced reset schedule |
Caller sets both together explicitly |
| Notify thresholds | [] (empty) — no notifications configured |
Caller populates notify_triggers explicitly |
| Suspend thresholds | null for both suspend_trigger and suspend_immediate_trigger — no suspend action configured |
Caller sets either or both explicitly |
| Notification recipients | [] (empty) — no implicit notification of any user |
Caller populates notify_users explicitly, referencing terraform-snowflake-user outputs |
The empty call (name only) produces a resource monitor that exists but governs nothing — no
credit tracking, no notifications, no suspension — consistent with this library's "the empty call
must produce the safe resource" convention. A caller has to type every additional argument to make the
monitor actually enforce a budget.
cd C:\GitHubCode\newsnowflakemodules\terraform-snowflake-resource-monitor
terraform init -backend=false
terraform validate
terraform fmt -checkPin the module source to ?ref=v1.0.0 — never a branch — in every caller. This is a plan-only
authoring pipeline: no terraform plan or terraform apply is ever run as part of authoring this
module. A human runs apply from a governed CI pipeline against a real Snowflake account.
terraform validate and terraform fmt -check are the offline proof gate this module ships
with:
- What they cover: type correctness (every variable's
object/scalar/set shape), thefrequencyenum, thefrequency/start_timestamppairing rule, and the triggers-only rejection rule — all threevalidation {}blocks fire onterraform validatewith no live Snowflake account required. HCL syntax and formatting are covered byfmt -check. - What only a real
plan/applyexercises: whether the executing role actually holdsCREATE RESOURCE MONITOR(privilege sufficiency), whethernotify_usersreferences existing Snowflake users (object-existence dependency this module deliberately does not check), and the destroy/recreate behavior triggered by unsetting every trigger on an existing monitor (aDESC/state-comparison-driven behavior invisible to a single-configurationvalidatepass).
$ terraform output
fully_qualified_name = "\"RM_WH_ETL\""
name = "RM_WH_ETL"
id = "\"RM_WH_ETL\""
| Symptom | Cause | Fix |
|---|---|---|
terraform validate fails with "A resource monitor cannot be created with only trigger fields set" |
Only notify_triggers/suspend_trigger/suspend_immediate_trigger were set, with none of credit_quota, frequency, start_timestamp, end_timestamp, or notify_users |
Set at least one non-trigger attribute alongside the trigger(s) — see Example 7 |
terraform validate fails with "frequency and start_timestamp must be set together" |
Only one of the pair was set | Set both, or leave both null |
Apply fails with a Snowflake authorization error on CREATE RESOURCE MONITOR |
Executing role lacks the privilege (commonly ACCOUNTADMIN-only) | Grant CREATE RESOURCE MONITOR to the executing role, or apply through a provider alias configured for ACCOUNTADMIN |
| A plan that removes every trigger from an existing monitor shows a destroy/recreate instead of an in-place update | Provider/Snowflake limitation — once triggers are set, they cannot be fully unset in place | Expected behavior; review the destroy/recreate carefully before applying, since it is a real object recreation, not a cosmetic diff |
Removing frequency or start_timestamp from HCL produces no diff on the next plan |
Provider has no unset support for these two parameters — the previously applied value is preserved on the Snowflake side | Set the field to a different explicit value to change it; deleting the argument alone does not reset it |
notify_users reference fails at apply with a Snowflake "user does not exist" error |
This module does not validate user existence at plan time | Confirm the referenced terraform-snowflake-user module has already been applied, or the user identifier is correct |
Import leaves frequency/start_timestamp blank in the generated configuration despite a value on the live object |
Known provider import gap for several resources (see this library's cross-cutting "Schema notes that bite" convention) | Compare against terraform show / show_output after import and add the missing arguments manually before the next plan |
- Provider resource docs:
snowflake_resource_monitor - Snowflake resource monitor concept guide: docs.snowflake.com/en/user-guide/resource-monitors
- Sibling modules:
terraform-snowflake-warehouse(consumesfully_qualified_name),terraform-snowflake-user(feedsnotify_users) - This module's
SCOPE.md