Organization budgets¶
Organization budgets let you define and track spend across multiple Snowflake accounts within one organization from a single object. Instead of maintaining separate account-level custom budgets for each account, you configure one organization budget and monitor aggregated spend from your org admin account.
Organization budgets support three configurable scope dimensions:
- Accounts: which accounts in the organization are measured.
- Service types: organization usage filtered by service type (for example, AI services).
- Tagged resources: spend on non-shared resources matched by organization tags.
Before you begin¶
Before creating an organization budget, confirm the following:
- Your organization has an organization account set up.
- You have the
GLOBALORGADMINrole in the org admin account. In Private Preview, onlyGLOBALORGADMINcan create and manage organization budgets. - The
ORGANIZATION$DBdatabase is accessible from the org admin account. - Premium views in the organization account are enabled. Organization budgets depend on organization usage data from these views.
- Organization tags are created and applied to resources before setting resource-tag scope. Each tag used
in scope requires the
APPLYBUDGETprivilege.
Currency¶
Each organization budget measures spend in the organization’s billing currency, derived from the organization’s current billing contract (for example, USD, EUR, GBP). You can’t change the currency of an existing organization budget. If your organization later changes its billing contract and thus its currency, create a new organization budget to track spend in the new currency.
Note
Organization budget spend reflects in-currency rows from organization usage. Cross-currency rollup across multiple contracts isn’t supported in Private Preview.
Create an organization budget¶
Organization budget instances must be created in ORGANIZATION$DB under the
BUDGETS schema. Custom schemas are currently not allowed.
After you create the organization budget:
- No spend is tracked until you configure scope for accounts and services (or tags).
- No notifications or custom actions fire until you set a spending limit and configure thresholds.
- Spend data appears after the next refresh. For timing details, see Latency.
Configure scope¶
Scope defines what the organization budget measures. Three procedures let you manage scope:
ADD_SCOPE: incrementally adds entries to existing scope.REMOVE_SCOPE: removes specific entries from existing scope.SET_SCOPE: atomically replaces all scope for one or more dimensions.
You can update multiple dimensions in one call by including more than one key in the JSON object argument.
Scope dimensions:
| Dimension | JSON key | Description | Combinable with |
|---|---|---|---|
| Account | accounts | Which organization accounts are measured | Either service_types or resource_tags |
| Service type | service_types | Organization usage filtered by service type | accounts only |
| Resource tag | resource_tags | Spend on non-shared tagged resources | accounts only |
Note that service_types and resource_tags are mutually exclusive. Setting one while the other exists
returns an error. To switch between them, clear the existing dimension first using SET_SCOPE.
Account scope¶
Account scope allows you to select which accounts the budget should track. Use ADD_SCOPE and REMOVE_SCOPE to update the
list incrementally, or SET_SCOPE to replace the account configuration in one single SQL statement.
Add specific accounts to scope:
Use ADD_SCOPE to incrementally append accounts to the existing inclusion list. This doesn’t
replace any accounts already in scope.
Remove specific accounts from scope:
Use REMOVE_SCOPE to drop individual accounts from the inclusion list. Accounts not in the list
are unaffected.
Track all accounts (including future accounts):
Use SET_SCOPE with "all": true to replace the account configuration so that every account in
the organization is measured. Accounts added to the organization in the future are automatically included.
Track all accounts except specific ones:
Use SET_SCOPE with "all": true and an excluded list to cover the entire organization while
carving out specific accounts. New accounts are auto-included unless they appear on the exclusion
list.
Replace the account list entirely with a specific set:
Use SET_SCOPE with "all": false and an included list to replace whatever account scope
currently exists with an explicit, fixed list. Only the listed accounts are measured.
Clear all account scope:
Pass an empty included list to remove all account scope. The budget stops tracking any accounts
until scope is reconfigured.
Note
When the budget is in ALL mode, ADD_SCOPE removes accounts from the exclusion list and
REMOVE_SCOPE adds accounts to the exclusion list. Explicit account and service-type lists using
SET_SCOPE are capped at 1,000 entries each.
Service-type scope¶
Service-type scope tracks spend for one or more service types across in-scope accounts.
Add specific service types:
Use ADD_SCOPE to incrementally add service types to the existing list. Service types already in
scope are unaffected.
Remove specific service types:
Use REMOVE_SCOPE to drop individual service types from the list. Other service types in scope
remain.
Track all service types:
Use SET_SCOPE with "all": true to replace the service-type configuration so that all service
types are measured, including any new service types introduced in the future.
Track all service types except specific ones:
Use SET_SCOPE with "all": true and an excluded list to cover all service types while
excluding specific ones from spend measurement.
Replace the service-type list entirely with a specific set:
Use SET_SCOPE with "all": false and an included list to replace whatever service-type scope
currently exists with a fixed list. Only the listed service types contribute to spend measurement.
Resource-tag scope¶
Resource-tag scope tracks spend on non-shared resources matched by organization tags. You can combine multiple tag/value pairs using UNION (match any) or INTERSECTION (match all).
Because the argument includes SYSTEM$REFERENCE calls, use OBJECT_CONSTRUCT and ARRAY_CONSTRUCT
to build it rather than PARSE_JSON.
Important
You must have the APPLYBUDGET privilege on each tag used in scope. Resource-tag scope and
service-type scope are mutually exclusive.
Tagged storage spend is tracked at the account level, not at the database level. Tags applied to individual databases aren’t used to attribute storage costs in resource-tag scope.
Add one tag/value pair:
Use ADD_SCOPE to incrementally add a tag/value pair to the existing tag scope. Existing pairs
are not affected. Pass a reference to the tag using SYSTEM$REFERENCE and specify the tag value
you want to match.
Remove a specific tag/value pair:
Use REMOVE_SCOPE to drop one tag/value pair from the scope. The pair must match exactly (both
tag reference and value). Other pairs in scope remain.
Replace tag scope with a UNION of tag/value pairs (match any):
Use SET_SCOPE with operator: UNION to track resources that match at least one of the listed
tag/value pairs. This atomically replaces all existing tag scope.
Replace tag scope with an INTERSECTION of tag/value pairs (match all):
Use SET_SCOPE with operator: INTERSECTION to track only resources that match every listed
tag/value pair simultaneously. This atomically replaces all existing tag scope.
Clear all tag scope:
Pass an empty tags array to remove all tag scope from the budget. Use this before switching to
service-type scope, since the two dimensions are mutually exclusive.
Combine dimensions in a single call¶
ADD_SCOPE, REMOVE_SCOPE, and SET_SCOPE all accept multiple dimension keys in one JSON
argument, letting you update accounts and service types atomically.
Add accounts and service types in one call:
Include both keys in the same JSON argument to update multiple dimensions at once. Both additions are applied atomically: no intermediate state is visible.
Replace both dimensions atomically:
Use SET_SCOPE with multiple keys to replace both account and service-type scope in a single call.
The entire scope configuration is swapped at once, so there’s no window where only one dimension is
updated.
Read current scope:
Use GET_ORG_BUDGET_SCOPE at any time to inspect the full scope configuration across all active
dimensions. The output reflects the current state regardless of which scope mode the budget is in.
Set a spending limit¶
Set the organization-level spending limit in the organization’s billing currency. The limit must be a positive number. The limit is required before notifications or custom actions can fire.
Check the current limit:
Use GET_SPENDING_LIMIT to retrieve the currently configured spending limit. This is also
available in GET_CONFIG alongside other budget settings.
View configuration¶
GET_CONFIG returns the current configuration of an organization budget instance in a single row.
Output columns:
| Column | Type | Description |
|---|---|---|
BUDGET_CURRENCY | VARCHAR | ISO currency code for the organization’s billing contract (for example, USD) |
SPEND_LIMIT | NUMBER | Configured spending limit in the budget’s currency |
NOTIFICATION_EMAIL | VARCHAR | Comma-separated list of email addresses configured to receive threshold alerts |
LAST_NOTIFICATION_TIME | NUMBER | Unix epoch timestamp (seconds) of the most recent notification sent, or null if none |
NOTIFICATION_MUTE_FLAG | BOOLEAN | Whether notifications are currently muted (TRUE = muted) |
REFRESH_TIER | VARCHAR | Active refresh tier (for example, TIER_6H) |
Example output:
| NOTIFICATION_EMAIL | LAST_NOTIFICATION_TIME | SPEND_LIMIT | NOTIFICATION_MUTE_FLAG | BUDGET_CURRENCY | REFRESH_TIER |
|---|---|---|---|---|---|
| admin@example.com | 1784689984 | 25000 | TRUE | USD | TIER_6H |
Configure notifications¶
Organization budgets send email alerts when actual or projected spend crosses a configured threshold.
Add notification thresholds¶
Each threshold policy combines a percentage of the spending limit with a spend strategy (ACTUAL or PROJECTED).
Set up email notifications¶
Email notifications are deduplicated: at most one email fires per 24 hours.
Mute notifications¶
Use SET_NOTIFICATION_MUTE_FLAG to suppress all email alerts without removing your threshold
configuration. This is useful during planned maintenance windows or testing. Set the flag back to
FALSE to re-enable notifications.
Configure custom actions¶
Custom actions are stored procedures that run when organization spend crosses a threshold. Up to 10 custom actions per organization budget instance are supported. Custom actions run only in the org admin account; a trigger can’t run a procedure in a non-organization account. Remote account execution isn’t supported in Private Preview.
Configure a cycle-start action¶
A cycle-start action runs once at the start of each UTC calendar month, independent of threshold evaluation. Use it to reset state between billing cycles (for example, re-enable suspended resources or send a summary notification).
The procedure must be created in a database that the SNOWFLAKE application can access, and you
must grant the SNOWFLAKE application USAGE on the database, schema, and procedure before
calling SET_CYCLE_START_ACTION.
Step 1: Create the stored procedure.
Create a stored procedure with
EXECUTE AS OWNER so it runs with the owner’s privileges when triggered by the organization budget:
Step 2: Grant the SNOWFLAKE application access to the procedure.
The organization budget runs as the SNOWFLAKE application. Grant it USAGE on the database,
schema, and procedure so it can invoke the stored procedure at cycle start:
Step 3: Set the cycle-start action.
Pass a SYSTEM$REFERENCE to the procedure and an ARRAY_CONSTRUCT() for the arguments. An empty
array is correct when the procedure takes no parameters:
Check the configured action:
Remove the cycle-start action:
View spending history¶
Use GET_SPENDING_HISTORY to view organization-level spend over time. The shape of the output depends on
how your budget is scoped.
Output columns common to all scope modes:
| Column | Type | Description |
|---|---|---|
USAGE_DATE | DATE | Usage date (UTC), aligned with USAGE_IN_CURRENCY_DAILY.usage_date |
CURRENCY | VARCHAR | Budget currency code (for example, USD) |
AMOUNT | NUMBER | Measured spend in that currency for that row |
ACCOUNT_NAME | VARCHAR | Snowflake account name for the usage row |
Service-type mode only:
| Column | Type | Description |
|---|---|---|
SERVICE_TYPE | VARCHAR | Billing service type (for example, COMPUTE, AI_SERVICES); one row per (date, account name, service type) |
Resource-tag mode only:
| Column | Type | Description |
|---|---|---|
ENTITY_TYPE | VARCHAR | Type of the tagged resource |
ENTITY_ID | VARCHAR | Identifier of the tagged resource |
In resource-tag mode, results show daily totals per usage date with no per-service-type breakdown.
To inspect which resources are being tracked, use GET_ORG_BUDGET_SCOPE.
Usage refresh¶
Organization budget spend is evaluated by an internal measurement task. By default, the refresh
interval is up to 6 hours (TIER_6H). You can set a low latency refresh tier (TIER_1H) when you create
or edit the budget.
For details on when spend first appears and when account-level changes show up in the organization budget, see Latency.
Latency¶
Organization budget spend data isn’t available immediately after you create a budget or change
scope. Timing depends on the active refresh interval (TIER_6H by default, or TIER_1H if you set
low latency refresh mode).
- First spend data after create: After you create a budget and configure scope, spend data appears after the next successful refresh (within the active refresh interval).
- Account-level changes: Usage and configuration changes in member accounts are reflected in the organization budget after the next refresh.
- Account-to-organization sync delay: Data from the account level can take up to 10 minutes to be reflected at the organization level, so organization and account budget figures may not match exactly at the same point in time.
Cost¶
Organization budgets run as cloud services compute. The cost is expected to be minimal for most organizations. The active refresh tier affects compute cost: switching from the default 6-hour tier to the 1-hour low latency tier increases compute cost by a factor of approximately 12.
To see the compute credits consumed by each organization budget instance in the current month,
query SERVERLESS_TASK_HISTORY joined to CLASS_INSTANCES in SNOWFLAKE.ACCOUNT_USAGE:
List organization budgets¶
You can list organization budgets with either of the following:
The result is filtered based on the calling role’s privileges:
GLOBALORGADMIN: sees all organization budgets in the organization.- Custom role with a
VIEWERorADMINinstance role: sees only the specific budgets for which that role has been granted an instance role. Grants on one budget don’t expose other budgets, and the filter applies even through inherited role hierarchies. - Role with no organization budget instance role: returns an empty result.
SHOW SNOWFLAKE.CORE.ORG_BUDGET IN ACCOUNT returns one row per organization budget instance visible
to the current role. Example output:
| created_on | name | database_name | schema_name | current_version | comment | owner | owner_role_type |
|---|---|---|---|---|---|---|---|
| 2026-07-22 18:23:33.138 -0700 | MARKETING_BUDGET | ORGANIZATION$DB | BUDGETS | 0.11 | GLOBALORGADMIN | ROLE | |
| 2026-07-22 09:58:36.962 -0700 | PLAYGROUND_BUDGET | ORGANIZATION$DB | BUDGETS | 0.11 | GLOBALORGADMIN | ROLE |
SYSTEM$SHOW_ORG_BUDGETS_IN_ACCOUNT returns a JSON array of the same organization budget instances
visible to the current role from the org admin account.
Roles and privileges¶
GLOBALORGADMIN has full access to create, configure, view, and drop organization budgets. You
can also delegate read-only or read-write access to custom roles using instance-level roles.
Delegating access to custom roles¶
You can grant read-only or read-write access to specific organization budget instances by granting
an instance-level role to a custom role. The custom role also needs USAGE on ORGANIZATION$DB and
the BUDGETS schema.
The following table summarizes what each instance role can do:
| Operation | VIEWER | ADMIN | GLOBALORGADMIN |
|---|---|---|---|
GET_CONFIG, GET_SPENDING_LIMIT, GET_ORG_BUDGET_SCOPE | ✓ | ✓ | ✓ |
GET_SPENDING_HISTORY, GET_NOTIFICATION_THRESHOLDS, GET_NOTIFICATION_EMAIL | ✓ | ✓ | ✓ |
SET_SPENDING_LIMIT, SET_SCOPE, ADD_SCOPE, REMOVE_SCOPE | — | ✓ | ✓ |
SET_EMAIL_NOTIFICATIONS, ADD_NOTIFICATION_THRESHOLD, SET_NOTIFICATION_MUTE_FLAG | — | ✓ | ✓ |
REFRESH_USAGE, SET_REFRESH_TIER | — | ✓ | ✓ |
CREATE SNOWFLAKE.CORE.ORG_BUDGET, DROP SNOWFLAKE.CORE.ORG_BUDGET | — | — | ✓ |
Instance roles are per-budget: a grant on one budget doesn’t give access to any other budget. Role hierarchy is respected, so a parent role inherits instance roles granted to any of its child roles.
Note
The !ADMIN instance role grants management access to a budget but not the ability to drop it.
DROP SNOWFLAKE.CORE.ORG_BUDGET is reserved for the role that owns the budget instance.
Delegating budget creation to custom roles¶
To let a custom role create organization budgets (without granting GLOBALORGADMIN), grant both
of the following:
A custom role with these grants can create and drop only the budgets it owns. It can’t drop budgets owned by other roles.
Required roles and privileges reference¶
The following table lists all the privileges and roles relevant to organization budgets, with the operations each one enables.
| Privilege or role | Create | Manage | Monitor | Notes |
|---|---|---|---|---|
GLOBALORGADMIN | ✓ | ✓ | ✓ | Full access to create, configure, view, and drop all organization budgets. No additional grants needed. |
SNOWFLAKE.ORG_BUDGET_CREATOR (database role) | ✓ | Grant this database role to enable a custom role to create organization budgets. | ||
CREATE SNOWFLAKE.CORE.ORG_BUDGET | ✓ | Grant this privilege on the schema that will contain the budget (for example, ORGANIZATION$DB.BUDGETS). | ||
USAGE (database) | ✓ | ✓ | ✓ | Grant USAGE on ORGANIZATION$DB to any custom role that creates, manages, or monitors budgets. |
USAGE (schema) | ✓ | ✓ | ✓ | Grant USAGE on the schema containing the budget (for example, ORGANIZATION$DB.BUDGETS). |
<budget>!VIEWER instance role | ✓ | Grants read-only access (GET_* methods) on a specific budget instance. See Delegating access to custom roles. | ||
<budget>!ADMIN instance role | ✓ | ✓ | Grants read-write access (GET_*, SET_*, ADD_*, REMOVE_*) on a specific budget instance. Does not grant DROP. See Delegating access to custom roles. | |
APPLYBUDGET (on organization tag) | ✓ | Required on each organization tag used in resource-tag scope. |
Limitations¶
The following features aren’t supported in Private Preview:
- Shared-resource tracking (
SET_USER_TAGS,ADD_SHARED_RESOURCE). - Credit-based spending limits. Limits use the organization’s billing currency only.
- Custom actions in remote (non-org-admin) accounts.
- Multi-currency rollup across multiple billing contracts.
- Resource-tag scope combined with service-type scope on the same instance.
Usage notes¶
- Organization budgets operate on a monthly cycle aligned to the UTC calendar month, matching account custom budgets.
- No spend is tracked until scope is configured. Notifications and actions require a spending limit and threshold to be set first.
- The spending limit must be a positive number.
- Setting service-type scope while resource-tag scope exists, or vice versa, returns an error.
Clear the existing dimension with
SET_SCOPEbefore switching. - In resource-tag mode, inspecting which resources are tracked requires
GET_ORG_BUDGET_SCOPEorGET_LINKED_RESOURCES_BY_TAG. Spending history doesn’t include a per-service-type breakdown in this mode. - Explicit account and service-type lists are capped at 1,000 entries. Use
{"all": true}or{"all": true, "excluded": [...]}for larger organizations. - If your organization’s billing currency changes, create a new organization budget. An existing instance keeps its original currency and can’t be updated.
- In resource-tag mode, tagged storage spend is tracked at the account level, not at the database level. Tags applied to individual databases aren’t used to attribute storage costs.