The gcp:billing/budget:Budget resource, part of the Pulumi GCP provider, defines billing budgets that track spending against limits and trigger alerts when thresholds are crossed. This guide focuses on three capabilities: fixed and relative budget amounts, spending filters by project and service, and notification routing with custom date ranges.
Budgets require a billing account ID and may reference project numbers, service IDs, or monitoring notification channels. The examples are intentionally small. Combine them with your own billing accounts, projects, and notification infrastructure.
Set a fixed spending limit with threshold alerts
Most billing budgets start by defining a fixed dollar amount and alerting when spending crosses percentage thresholds.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const account = gcp.organizations.getBillingAccount({
billingAccount: "000000-0000000-0000000-000000",
});
const budget = new gcp.billing.Budget("budget", {
billingAccount: account.then(account => account.id),
displayName: "Example Billing Budget",
amount: {
specifiedAmount: {
currencyCode: "USD",
units: "100000",
},
},
thresholdRules: [{
thresholdPercent: 0.5,
}],
});
import pulumi
import pulumi_gcp as gcp
account = gcp.organizations.get_billing_account(billing_account="000000-0000000-0000000-000000")
budget = gcp.billing.Budget("budget",
billing_account=account.id,
display_name="Example Billing Budget",
amount={
"specified_amount": {
"currency_code": "USD",
"units": "100000",
},
},
threshold_rules=[{
"threshold_percent": 0.5,
}])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/billing"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
account, err := organizations.GetBillingAccount(ctx, &organizations.GetBillingAccountArgs{
BillingAccount: pulumi.StringRef("000000-0000000-0000000-000000"),
}, nil)
if err != nil {
return err
}
_, err = billing.NewBudget(ctx, "budget", &billing.BudgetArgs{
BillingAccount: pulumi.String(account.Id),
DisplayName: pulumi.String("Example Billing Budget"),
Amount: &billing.BudgetAmountArgs{
SpecifiedAmount: &billing.BudgetAmountSpecifiedAmountArgs{
CurrencyCode: pulumi.String("USD"),
Units: pulumi.String("100000"),
},
},
ThresholdRules: billing.BudgetThresholdRuleArray{
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(0.5),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var account = Gcp.Organizations.GetBillingAccount.Invoke(new()
{
BillingAccount = "000000-0000000-0000000-000000",
});
var budget = new Gcp.Billing.Budget("budget", new()
{
BillingAccount = account.Apply(getBillingAccountResult => getBillingAccountResult.Id),
DisplayName = "Example Billing Budget",
Amount = new Gcp.Billing.Inputs.BudgetAmountArgs
{
SpecifiedAmount = new Gcp.Billing.Inputs.BudgetAmountSpecifiedAmountArgs
{
CurrencyCode = "USD",
Units = "100000",
},
},
ThresholdRules = new[]
{
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 0.5,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetBillingAccountArgs;
import com.pulumi.gcp.billing.Budget;
import com.pulumi.gcp.billing.BudgetArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountSpecifiedAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetThresholdRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var account = OrganizationsFunctions.getBillingAccount(GetBillingAccountArgs.builder()
.billingAccount("000000-0000000-0000000-000000")
.build());
var budget = new Budget("budget", BudgetArgs.builder()
.billingAccount(account.id())
.displayName("Example Billing Budget")
.amount(BudgetAmountArgs.builder()
.specifiedAmount(BudgetAmountSpecifiedAmountArgs.builder()
.currencyCode("USD")
.units("100000")
.build())
.build())
.thresholdRules(BudgetThresholdRuleArgs.builder()
.thresholdPercent(0.5)
.build())
.build());
}
}
resources:
budget:
type: gcp:billing:Budget
properties:
billingAccount: ${account.id}
displayName: Example Billing Budget
amount:
specifiedAmount:
currencyCode: USD
units: '100000'
thresholdRules:
- thresholdPercent: 0.5
variables:
account:
fn::invoke:
function: gcp:organizations:getBillingAccount
arguments:
billingAccount: 000000-0000000-0000000-000000
When actual spending reaches the threshold percentage, the budget triggers an alert. The amount property sets a fixed limit using specifiedAmount with a currency code and units (in this case, $100,000 USD). The thresholdRules array defines one or more percentage thresholds; here, an alert fires at 50% of the budget.
Track spending relative to the previous period
Teams with predictable monthly costs often budget based on the previous period’s spending rather than a fixed amount.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const account = gcp.organizations.getBillingAccount({
billingAccount: "000000-0000000-0000000-000000",
});
const project = gcp.organizations.getProject({});
const budget = new gcp.billing.Budget("budget", {
billingAccount: account.then(account => account.id),
displayName: "Example Billing Budget",
budgetFilter: {
projects: [project.then(project => `projects/${project.number}`)],
},
amount: {
lastPeriodAmount: true,
},
thresholdRules: [{
thresholdPercent: 10,
}],
});
import pulumi
import pulumi_gcp as gcp
account = gcp.organizations.get_billing_account(billing_account="000000-0000000-0000000-000000")
project = gcp.organizations.get_project()
budget = gcp.billing.Budget("budget",
billing_account=account.id,
display_name="Example Billing Budget",
budget_filter={
"projects": [f"projects/{project.number}"],
},
amount={
"last_period_amount": True,
},
threshold_rules=[{
"threshold_percent": 10,
}])
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/billing"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
account, err := organizations.GetBillingAccount(ctx, &organizations.GetBillingAccountArgs{
BillingAccount: pulumi.StringRef("000000-0000000-0000000-000000"),
}, nil)
if err != nil {
return err
}
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
_, err = billing.NewBudget(ctx, "budget", &billing.BudgetArgs{
BillingAccount: pulumi.String(account.Id),
DisplayName: pulumi.String("Example Billing Budget"),
BudgetFilter: &billing.BudgetBudgetFilterArgs{
Projects: pulumi.StringArray{
pulumi.Sprintf("projects/%v", project.Number),
},
},
Amount: &billing.BudgetAmountArgs{
LastPeriodAmount: pulumi.Bool(true),
},
ThresholdRules: billing.BudgetThresholdRuleArray{
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(10),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var account = Gcp.Organizations.GetBillingAccount.Invoke(new()
{
BillingAccount = "000000-0000000-0000000-000000",
});
var project = Gcp.Organizations.GetProject.Invoke();
var budget = new Gcp.Billing.Budget("budget", new()
{
BillingAccount = account.Apply(getBillingAccountResult => getBillingAccountResult.Id),
DisplayName = "Example Billing Budget",
BudgetFilter = new Gcp.Billing.Inputs.BudgetBudgetFilterArgs
{
Projects = new[]
{
$"projects/{project.Apply(getProjectResult => getProjectResult.Number)}",
},
},
Amount = new Gcp.Billing.Inputs.BudgetAmountArgs
{
LastPeriodAmount = true,
},
ThresholdRules = new[]
{
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 10,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetBillingAccountArgs;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.billing.Budget;
import com.pulumi.gcp.billing.BudgetArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetThresholdRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var account = OrganizationsFunctions.getBillingAccount(GetBillingAccountArgs.builder()
.billingAccount("000000-0000000-0000000-000000")
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var budget = new Budget("budget", BudgetArgs.builder()
.billingAccount(account.id())
.displayName("Example Billing Budget")
.budgetFilter(BudgetBudgetFilterArgs.builder()
.projects(String.format("projects/%s", project.number()))
.build())
.amount(BudgetAmountArgs.builder()
.lastPeriodAmount(true)
.build())
.thresholdRules(BudgetThresholdRuleArgs.builder()
.thresholdPercent(10.0)
.build())
.build());
}
}
resources:
budget:
type: gcp:billing:Budget
properties:
billingAccount: ${account.id}
displayName: Example Billing Budget
budgetFilter:
projects:
- projects/${project.number}
amount:
lastPeriodAmount: true
thresholdRules:
- thresholdPercent: 10
variables:
account:
fn::invoke:
function: gcp:organizations:getBillingAccount
arguments:
billingAccount: 000000-0000000-0000000-000000
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
Setting lastPeriodAmount to true makes the budget track spending relative to the previous billing period’s total. The budgetFilter property scopes the budget to specific projects using their project numbers. This configuration alerts when current spending exceeds 10% of last period’s total for the filtered projects.
Filter spending by projects, services, and credits
Organizations tracking costs for specific workloads need to filter budgets by project, service, or credit type.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const account = gcp.organizations.getBillingAccount({
billingAccount: "000000-0000000-0000000-000000",
});
const project = gcp.organizations.getProject({});
const budget = new gcp.billing.Budget("budget", {
billingAccount: account.then(account => account.id),
displayName: "Example Billing Budget",
budgetFilter: {
projects: [project.then(project => `projects/${project.number}`)],
creditTypesTreatment: "INCLUDE_SPECIFIED_CREDITS",
services: ["services/24E6-581D-38E5"],
creditTypes: [
"PROMOTION",
"FREE_TIER",
],
resourceAncestors: ["organizations/123456789"],
},
amount: {
specifiedAmount: {
currencyCode: "USD",
units: "100000",
},
},
thresholdRules: [
{
thresholdPercent: 0.5,
},
{
thresholdPercent: 0.9,
spendBasis: "FORECASTED_SPEND",
},
],
});
import pulumi
import pulumi_gcp as gcp
account = gcp.organizations.get_billing_account(billing_account="000000-0000000-0000000-000000")
project = gcp.organizations.get_project()
budget = gcp.billing.Budget("budget",
billing_account=account.id,
display_name="Example Billing Budget",
budget_filter={
"projects": [f"projects/{project.number}"],
"credit_types_treatment": "INCLUDE_SPECIFIED_CREDITS",
"services": ["services/24E6-581D-38E5"],
"credit_types": [
"PROMOTION",
"FREE_TIER",
],
"resource_ancestors": ["organizations/123456789"],
},
amount={
"specified_amount": {
"currency_code": "USD",
"units": "100000",
},
},
threshold_rules=[
{
"threshold_percent": 0.5,
},
{
"threshold_percent": 0.9,
"spend_basis": "FORECASTED_SPEND",
},
])
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/billing"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
account, err := organizations.GetBillingAccount(ctx, &organizations.GetBillingAccountArgs{
BillingAccount: pulumi.StringRef("000000-0000000-0000000-000000"),
}, nil)
if err != nil {
return err
}
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
_, err = billing.NewBudget(ctx, "budget", &billing.BudgetArgs{
BillingAccount: pulumi.String(account.Id),
DisplayName: pulumi.String("Example Billing Budget"),
BudgetFilter: &billing.BudgetBudgetFilterArgs{
Projects: pulumi.StringArray{
pulumi.Sprintf("projects/%v", project.Number),
},
CreditTypesTreatment: pulumi.String("INCLUDE_SPECIFIED_CREDITS"),
Services: pulumi.StringArray{
pulumi.String("services/24E6-581D-38E5"),
},
CreditTypes: pulumi.StringArray{
pulumi.String("PROMOTION"),
pulumi.String("FREE_TIER"),
},
ResourceAncestors: pulumi.StringArray{
pulumi.String("organizations/123456789"),
},
},
Amount: &billing.BudgetAmountArgs{
SpecifiedAmount: &billing.BudgetAmountSpecifiedAmountArgs{
CurrencyCode: pulumi.String("USD"),
Units: pulumi.String("100000"),
},
},
ThresholdRules: billing.BudgetThresholdRuleArray{
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(0.5),
},
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(0.9),
SpendBasis: pulumi.String("FORECASTED_SPEND"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var account = Gcp.Organizations.GetBillingAccount.Invoke(new()
{
BillingAccount = "000000-0000000-0000000-000000",
});
var project = Gcp.Organizations.GetProject.Invoke();
var budget = new Gcp.Billing.Budget("budget", new()
{
BillingAccount = account.Apply(getBillingAccountResult => getBillingAccountResult.Id),
DisplayName = "Example Billing Budget",
BudgetFilter = new Gcp.Billing.Inputs.BudgetBudgetFilterArgs
{
Projects = new[]
{
$"projects/{project.Apply(getProjectResult => getProjectResult.Number)}",
},
CreditTypesTreatment = "INCLUDE_SPECIFIED_CREDITS",
Services = new[]
{
"services/24E6-581D-38E5",
},
CreditTypes = new[]
{
"PROMOTION",
"FREE_TIER",
},
ResourceAncestors = new[]
{
"organizations/123456789",
},
},
Amount = new Gcp.Billing.Inputs.BudgetAmountArgs
{
SpecifiedAmount = new Gcp.Billing.Inputs.BudgetAmountSpecifiedAmountArgs
{
CurrencyCode = "USD",
Units = "100000",
},
},
ThresholdRules = new[]
{
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 0.5,
},
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 0.9,
SpendBasis = "FORECASTED_SPEND",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetBillingAccountArgs;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.billing.Budget;
import com.pulumi.gcp.billing.BudgetArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountSpecifiedAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetThresholdRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var account = OrganizationsFunctions.getBillingAccount(GetBillingAccountArgs.builder()
.billingAccount("000000-0000000-0000000-000000")
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var budget = new Budget("budget", BudgetArgs.builder()
.billingAccount(account.id())
.displayName("Example Billing Budget")
.budgetFilter(BudgetBudgetFilterArgs.builder()
.projects(String.format("projects/%s", project.number()))
.creditTypesTreatment("INCLUDE_SPECIFIED_CREDITS")
.services("services/24E6-581D-38E5")
.creditTypes(
"PROMOTION",
"FREE_TIER")
.resourceAncestors("organizations/123456789")
.build())
.amount(BudgetAmountArgs.builder()
.specifiedAmount(BudgetAmountSpecifiedAmountArgs.builder()
.currencyCode("USD")
.units("100000")
.build())
.build())
.thresholdRules(
BudgetThresholdRuleArgs.builder()
.thresholdPercent(0.5)
.build(),
BudgetThresholdRuleArgs.builder()
.thresholdPercent(0.9)
.spendBasis("FORECASTED_SPEND")
.build())
.build());
}
}
resources:
budget:
type: gcp:billing:Budget
properties:
billingAccount: ${account.id}
displayName: Example Billing Budget
budgetFilter:
projects:
- projects/${project.number}
creditTypesTreatment: INCLUDE_SPECIFIED_CREDITS
services:
- services/24E6-581D-38E5
creditTypes:
- PROMOTION
- FREE_TIER
resourceAncestors:
- organizations/123456789
amount:
specifiedAmount:
currencyCode: USD
units: '100000'
thresholdRules:
- thresholdPercent: 0.5
- thresholdPercent: 0.9
spendBasis: FORECASTED_SPEND
variables:
account:
fn::invoke:
function: gcp:organizations:getBillingAccount
arguments:
billingAccount: 000000-0000000-0000000-000000
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The budgetFilter property controls which spending counts toward the budget. The projects array limits tracking to specific project numbers. The services array filters to particular GCP services (here, Compute Engine). The creditTypes and creditTypesTreatment properties determine whether promotional credits and free tier usage count toward the budget. The resourceAncestors property can scope budgets to entire organizations or folders.
Send alerts to monitoring notification channels
Budget alerts become actionable when routed to notification channels that reach the right teams.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const account = gcp.organizations.getBillingAccount({
billingAccount: "000000-0000000-0000000-000000",
});
const project = gcp.organizations.getProject({});
const notificationChannel = new gcp.monitoring.NotificationChannel("notification_channel", {
displayName: "Example Notification Channel",
type: "email",
labels: {
email_address: "address@example.com",
},
});
const budget = new gcp.billing.Budget("budget", {
billingAccount: account.then(account => account.id),
displayName: "Example Billing Budget",
budgetFilter: {
projects: [project.then(project => `projects/${project.number}`)],
},
amount: {
specifiedAmount: {
currencyCode: "USD",
units: "100000",
},
},
thresholdRules: [
{
thresholdPercent: 1,
},
{
thresholdPercent: 1,
spendBasis: "FORECASTED_SPEND",
},
],
allUpdatesRule: {
monitoringNotificationChannels: [notificationChannel.id],
disableDefaultIamRecipients: true,
},
});
import pulumi
import pulumi_gcp as gcp
account = gcp.organizations.get_billing_account(billing_account="000000-0000000-0000000-000000")
project = gcp.organizations.get_project()
notification_channel = gcp.monitoring.NotificationChannel("notification_channel",
display_name="Example Notification Channel",
type="email",
labels={
"email_address": "address@example.com",
})
budget = gcp.billing.Budget("budget",
billing_account=account.id,
display_name="Example Billing Budget",
budget_filter={
"projects": [f"projects/{project.number}"],
},
amount={
"specified_amount": {
"currency_code": "USD",
"units": "100000",
},
},
threshold_rules=[
{
"threshold_percent": 1,
},
{
"threshold_percent": 1,
"spend_basis": "FORECASTED_SPEND",
},
],
all_updates_rule={
"monitoring_notification_channels": [notification_channel.id],
"disable_default_iam_recipients": True,
})
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/billing"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
account, err := organizations.GetBillingAccount(ctx, &organizations.GetBillingAccountArgs{
BillingAccount: pulumi.StringRef("000000-0000000-0000000-000000"),
}, nil)
if err != nil {
return err
}
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
notificationChannel, err := monitoring.NewNotificationChannel(ctx, "notification_channel", &monitoring.NotificationChannelArgs{
DisplayName: pulumi.String("Example Notification Channel"),
Type: pulumi.String("email"),
Labels: pulumi.StringMap{
"email_address": pulumi.String("address@example.com"),
},
})
if err != nil {
return err
}
_, err = billing.NewBudget(ctx, "budget", &billing.BudgetArgs{
BillingAccount: pulumi.String(account.Id),
DisplayName: pulumi.String("Example Billing Budget"),
BudgetFilter: &billing.BudgetBudgetFilterArgs{
Projects: pulumi.StringArray{
pulumi.Sprintf("projects/%v", project.Number),
},
},
Amount: &billing.BudgetAmountArgs{
SpecifiedAmount: &billing.BudgetAmountSpecifiedAmountArgs{
CurrencyCode: pulumi.String("USD"),
Units: pulumi.String("100000"),
},
},
ThresholdRules: billing.BudgetThresholdRuleArray{
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(1),
},
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(1),
SpendBasis: pulumi.String("FORECASTED_SPEND"),
},
},
AllUpdatesRule: &billing.BudgetAllUpdatesRuleArgs{
MonitoringNotificationChannels: pulumi.StringArray{
notificationChannel.ID(),
},
DisableDefaultIamRecipients: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var account = Gcp.Organizations.GetBillingAccount.Invoke(new()
{
BillingAccount = "000000-0000000-0000000-000000",
});
var project = Gcp.Organizations.GetProject.Invoke();
var notificationChannel = new Gcp.Monitoring.NotificationChannel("notification_channel", new()
{
DisplayName = "Example Notification Channel",
Type = "email",
Labels =
{
{ "email_address", "address@example.com" },
},
});
var budget = new Gcp.Billing.Budget("budget", new()
{
BillingAccount = account.Apply(getBillingAccountResult => getBillingAccountResult.Id),
DisplayName = "Example Billing Budget",
BudgetFilter = new Gcp.Billing.Inputs.BudgetBudgetFilterArgs
{
Projects = new[]
{
$"projects/{project.Apply(getProjectResult => getProjectResult.Number)}",
},
},
Amount = new Gcp.Billing.Inputs.BudgetAmountArgs
{
SpecifiedAmount = new Gcp.Billing.Inputs.BudgetAmountSpecifiedAmountArgs
{
CurrencyCode = "USD",
Units = "100000",
},
},
ThresholdRules = new[]
{
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 1,
},
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 1,
SpendBasis = "FORECASTED_SPEND",
},
},
AllUpdatesRule = new Gcp.Billing.Inputs.BudgetAllUpdatesRuleArgs
{
MonitoringNotificationChannels = new[]
{
notificationChannel.Id,
},
DisableDefaultIamRecipients = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetBillingAccountArgs;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.monitoring.NotificationChannel;
import com.pulumi.gcp.monitoring.NotificationChannelArgs;
import com.pulumi.gcp.billing.Budget;
import com.pulumi.gcp.billing.BudgetArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountSpecifiedAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetThresholdRuleArgs;
import com.pulumi.gcp.billing.inputs.BudgetAllUpdatesRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var account = OrganizationsFunctions.getBillingAccount(GetBillingAccountArgs.builder()
.billingAccount("000000-0000000-0000000-000000")
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var notificationChannel = new NotificationChannel("notificationChannel", NotificationChannelArgs.builder()
.displayName("Example Notification Channel")
.type("email")
.labels(Map.of("email_address", "address@example.com"))
.build());
var budget = new Budget("budget", BudgetArgs.builder()
.billingAccount(account.id())
.displayName("Example Billing Budget")
.budgetFilter(BudgetBudgetFilterArgs.builder()
.projects(String.format("projects/%s", project.number()))
.build())
.amount(BudgetAmountArgs.builder()
.specifiedAmount(BudgetAmountSpecifiedAmountArgs.builder()
.currencyCode("USD")
.units("100000")
.build())
.build())
.thresholdRules(
BudgetThresholdRuleArgs.builder()
.thresholdPercent(1.0)
.build(),
BudgetThresholdRuleArgs.builder()
.thresholdPercent(1.0)
.spendBasis("FORECASTED_SPEND")
.build())
.allUpdatesRule(BudgetAllUpdatesRuleArgs.builder()
.monitoringNotificationChannels(notificationChannel.id())
.disableDefaultIamRecipients(true)
.build())
.build());
}
}
resources:
budget:
type: gcp:billing:Budget
properties:
billingAccount: ${account.id}
displayName: Example Billing Budget
budgetFilter:
projects:
- projects/${project.number}
amount:
specifiedAmount:
currencyCode: USD
units: '100000'
thresholdRules:
- thresholdPercent: 1
- thresholdPercent: 1
spendBasis: FORECASTED_SPEND
allUpdatesRule:
monitoringNotificationChannels:
- ${notificationChannel.id}
disableDefaultIamRecipients: true
notificationChannel:
type: gcp:monitoring:NotificationChannel
name: notification_channel
properties:
displayName: Example Notification Channel
type: email
labels:
email_address: address@example.com
variables:
account:
fn::invoke:
function: gcp:organizations:getBillingAccount
arguments:
billingAccount: 000000-0000000-0000000-000000
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The allUpdatesRule property defines where alerts are sent. The monitoringNotificationChannels array lists notification channel IDs (email, Slack, PagerDuty, etc.). Setting disableDefaultIamRecipients to true prevents automatic notifications to billing account IAM members, giving you full control over who receives alerts.
Define budgets for custom date ranges
Projects with fixed timelines or fiscal years that don’t align with calendar months need custom budget periods.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const account = gcp.organizations.getBillingAccount({
billingAccount: "000000-0000000-0000000-000000",
});
const project = gcp.organizations.getProject({});
const budget = new gcp.billing.Budget("budget", {
billingAccount: account.then(account => account.id),
displayName: "Example Billing Budget",
budgetFilter: {
projects: [project.then(project => `projects/${project.number}`)],
creditTypesTreatment: "EXCLUDE_ALL_CREDITS",
services: ["services/24E6-581D-38E5"],
customPeriod: {
startDate: {
year: 2022,
month: 1,
day: 1,
},
endDate: {
year: 2023,
month: 12,
day: 31,
},
},
},
amount: {
specifiedAmount: {
currencyCode: "USD",
units: "100000",
},
},
thresholdRules: [
{
thresholdPercent: 0.5,
},
{
thresholdPercent: 0.9,
},
],
});
import pulumi
import pulumi_gcp as gcp
account = gcp.organizations.get_billing_account(billing_account="000000-0000000-0000000-000000")
project = gcp.organizations.get_project()
budget = gcp.billing.Budget("budget",
billing_account=account.id,
display_name="Example Billing Budget",
budget_filter={
"projects": [f"projects/{project.number}"],
"credit_types_treatment": "EXCLUDE_ALL_CREDITS",
"services": ["services/24E6-581D-38E5"],
"custom_period": {
"start_date": {
"year": 2022,
"month": 1,
"day": 1,
},
"end_date": {
"year": 2023,
"month": 12,
"day": 31,
},
},
},
amount={
"specified_amount": {
"currency_code": "USD",
"units": "100000",
},
},
threshold_rules=[
{
"threshold_percent": 0.5,
},
{
"threshold_percent": 0.9,
},
])
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/billing"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
account, err := organizations.GetBillingAccount(ctx, &organizations.GetBillingAccountArgs{
BillingAccount: pulumi.StringRef("000000-0000000-0000000-000000"),
}, nil)
if err != nil {
return err
}
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
_, err = billing.NewBudget(ctx, "budget", &billing.BudgetArgs{
BillingAccount: pulumi.String(account.Id),
DisplayName: pulumi.String("Example Billing Budget"),
BudgetFilter: &billing.BudgetBudgetFilterArgs{
Projects: pulumi.StringArray{
pulumi.Sprintf("projects/%v", project.Number),
},
CreditTypesTreatment: pulumi.String("EXCLUDE_ALL_CREDITS"),
Services: pulumi.StringArray{
pulumi.String("services/24E6-581D-38E5"),
},
CustomPeriod: &billing.BudgetBudgetFilterCustomPeriodArgs{
StartDate: &billing.BudgetBudgetFilterCustomPeriodStartDateArgs{
Year: pulumi.Int(2022),
Month: pulumi.Int(1),
Day: pulumi.Int(1),
},
EndDate: &billing.BudgetBudgetFilterCustomPeriodEndDateArgs{
Year: pulumi.Int(2023),
Month: pulumi.Int(12),
Day: pulumi.Int(31),
},
},
},
Amount: &billing.BudgetAmountArgs{
SpecifiedAmount: &billing.BudgetAmountSpecifiedAmountArgs{
CurrencyCode: pulumi.String("USD"),
Units: pulumi.String("100000"),
},
},
ThresholdRules: billing.BudgetThresholdRuleArray{
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(0.5),
},
&billing.BudgetThresholdRuleArgs{
ThresholdPercent: pulumi.Float64(0.9),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var account = Gcp.Organizations.GetBillingAccount.Invoke(new()
{
BillingAccount = "000000-0000000-0000000-000000",
});
var project = Gcp.Organizations.GetProject.Invoke();
var budget = new Gcp.Billing.Budget("budget", new()
{
BillingAccount = account.Apply(getBillingAccountResult => getBillingAccountResult.Id),
DisplayName = "Example Billing Budget",
BudgetFilter = new Gcp.Billing.Inputs.BudgetBudgetFilterArgs
{
Projects = new[]
{
$"projects/{project.Apply(getProjectResult => getProjectResult.Number)}",
},
CreditTypesTreatment = "EXCLUDE_ALL_CREDITS",
Services = new[]
{
"services/24E6-581D-38E5",
},
CustomPeriod = new Gcp.Billing.Inputs.BudgetBudgetFilterCustomPeriodArgs
{
StartDate = new Gcp.Billing.Inputs.BudgetBudgetFilterCustomPeriodStartDateArgs
{
Year = 2022,
Month = 1,
Day = 1,
},
EndDate = new Gcp.Billing.Inputs.BudgetBudgetFilterCustomPeriodEndDateArgs
{
Year = 2023,
Month = 12,
Day = 31,
},
},
},
Amount = new Gcp.Billing.Inputs.BudgetAmountArgs
{
SpecifiedAmount = new Gcp.Billing.Inputs.BudgetAmountSpecifiedAmountArgs
{
CurrencyCode = "USD",
Units = "100000",
},
},
ThresholdRules = new[]
{
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 0.5,
},
new Gcp.Billing.Inputs.BudgetThresholdRuleArgs
{
ThresholdPercent = 0.9,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetBillingAccountArgs;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.billing.Budget;
import com.pulumi.gcp.billing.BudgetArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterCustomPeriodArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterCustomPeriodStartDateArgs;
import com.pulumi.gcp.billing.inputs.BudgetBudgetFilterCustomPeriodEndDateArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetAmountSpecifiedAmountArgs;
import com.pulumi.gcp.billing.inputs.BudgetThresholdRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var account = OrganizationsFunctions.getBillingAccount(GetBillingAccountArgs.builder()
.billingAccount("000000-0000000-0000000-000000")
.build());
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var budget = new Budget("budget", BudgetArgs.builder()
.billingAccount(account.id())
.displayName("Example Billing Budget")
.budgetFilter(BudgetBudgetFilterArgs.builder()
.projects(String.format("projects/%s", project.number()))
.creditTypesTreatment("EXCLUDE_ALL_CREDITS")
.services("services/24E6-581D-38E5")
.customPeriod(BudgetBudgetFilterCustomPeriodArgs.builder()
.startDate(BudgetBudgetFilterCustomPeriodStartDateArgs.builder()
.year(2022)
.month(1)
.day(1)
.build())
.endDate(BudgetBudgetFilterCustomPeriodEndDateArgs.builder()
.year(2023)
.month(12)
.day(31)
.build())
.build())
.build())
.amount(BudgetAmountArgs.builder()
.specifiedAmount(BudgetAmountSpecifiedAmountArgs.builder()
.currencyCode("USD")
.units("100000")
.build())
.build())
.thresholdRules(
BudgetThresholdRuleArgs.builder()
.thresholdPercent(0.5)
.build(),
BudgetThresholdRuleArgs.builder()
.thresholdPercent(0.9)
.build())
.build());
}
}
resources:
budget:
type: gcp:billing:Budget
properties:
billingAccount: ${account.id}
displayName: Example Billing Budget
budgetFilter:
projects:
- projects/${project.number}
creditTypesTreatment: EXCLUDE_ALL_CREDITS
services:
- services/24E6-581D-38E5
customPeriod:
startDate:
year: 2022
month: 1
day: 1
endDate:
year: 2023
month: 12
day: 31
amount:
specifiedAmount:
currencyCode: USD
units: '100000'
thresholdRules:
- thresholdPercent: 0.5
- thresholdPercent: 0.9
variables:
account:
fn::invoke:
function: gcp:organizations:getBillingAccount
arguments:
billingAccount: 000000-0000000-0000000-000000
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The customPeriod property inside budgetFilter defines a specific date range for the budget. The startDate and endDate properties set the beginning and end of the tracking period. This is useful for project-based budgets or fiscal years that don’t match calendar boundaries. The creditTypesTreatment property set to EXCLUDE_ALL_CREDITS ensures only actual spending (not credits) counts toward the budget.
Beyond these examples
These snippets focus on specific budget-level features: fixed and relative budget amounts, spending filters, and notification routing and custom periods. They’re intentionally minimal rather than full cost management solutions.
The examples may reference pre-existing infrastructure such as billing accounts with known IDs, projects with known numbers, and monitoring notification channels for alert routing. They focus on configuring the budget rather than provisioning the surrounding billing infrastructure.
To keep things focused, common budget patterns are omitted, including:
- Forecasted spend thresholds (spendBasis property)
- Project-level recipient notifications (enableProjectLevelRecipients)
- Calendar period configuration (alternative to customPeriod)
- Ownership scope controls (ownershipScope property)
These omissions are intentional: the goal is to illustrate how each budget feature is wired, not provide drop-in cost management modules. See the Billing Budget resource reference for all available configuration options.
Let's configure GCP Billing Budgets
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Authentication & Permissions
billing_project and user_project_override = true in your provider configuration. Your account also needs the serviceusage.services.use permission on the billing project.Budget Configuration
billingAccount is immutable. Changing it forces recreation of the budget resource.specifiedAmount sets a fixed budget amount in a specific currency, while lastPeriodAmount automatically uses the previous period’s spend as your budget. These options are mutually exclusive.Alerts & Notifications
thresholdRules with threshold percentages (e.g., 0.5 for 50%). You can set spendBasis to CURRENT_SPEND (default) for actual spend or FORECASTED_SPEND to alert on projected spend.thresholdRules trigger alerts only when specific spending thresholds are crossed. allUpdatesRule sends notifications on every spend update, regardless of thresholds.allUpdatesRule.monitoringNotificationChannels with notification channel IDs. You can also set disableDefaultIamRecipients to control whether IAM-based recipients receive alerts.allUpdatesRule.enableProjectLevelRecipients = true to automatically notify project billing administrators.Filtering & Scope
budgetFilter to scope your budget. Set projects with project numbers (format: projects/{number}), services with service IDs, or resourceAncestors with organization/folder IDs.budgetFilter.creditTypesTreatment to control credit handling. Use INCLUDE_SPECIFIED_CREDITS with a creditTypes list, or EXCLUDE_ALL_CREDITS to ignore all credits.budgetFilter.customPeriod with startDate and endDate objects specifying year, month, and day.Using a different cloud?
Explore monitoring guides for other cloud providers: