Configure GCP Service-Level Objectives

The gcp:monitoring/slo:Slo resource, part of the Pulumi GCP provider, defines Service-Level Objectives that measure service quality against performance goals over evaluation periods. This guide focuses on three capabilities: basic SLIs for latency tracking, request-based SLIs with distribution cuts, and windows-based SLIs with metric filters and aggregations.

SLOs reference existing monitoring services and rely on metric data from those services. The examples are intentionally small. Combine them with your own monitoring services and alert policies.

Track App Engine latency with basic SLI

Teams monitoring App Engine services often start with latency-based SLOs that measure whether requests complete within acceptable time bounds.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = gcp.monitoring.getAppEngineService({
    moduleId: "default",
});
const appengSlo = new gcp.monitoring.Slo("appeng_slo", {
    service: _default.then(_default => _default.serviceId),
    sloId: "ae-slo",
    displayName: "Test SLO for App Engine",
    goal: 0.9,
    calendarPeriod: "DAY",
    basicSli: {
        latency: {
            threshold: "1s",
        },
    },
    userLabels: {
        my_key: "my_value",
        my_other_key: "my_other_value",
    },
});
import pulumi
import pulumi_gcp as gcp

default = gcp.monitoring.get_app_engine_service(module_id="default")
appeng_slo = gcp.monitoring.Slo("appeng_slo",
    service=default.service_id,
    slo_id="ae-slo",
    display_name="Test SLO for App Engine",
    goal=0.9,
    calendar_period="DAY",
    basic_sli={
        "latency": {
            "threshold": "1s",
        },
    },
    user_labels={
        "my_key": "my_value",
        "my_other_key": "my_other_value",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := monitoring.GetAppEngineService(ctx, &monitoring.GetAppEngineServiceArgs{
			ModuleId: "default",
		}, nil)
		if err != nil {
			return err
		}
		_, err = monitoring.NewSlo(ctx, "appeng_slo", &monitoring.SloArgs{
			Service:        pulumi.String(_default.ServiceId),
			SloId:          pulumi.String("ae-slo"),
			DisplayName:    pulumi.String("Test SLO for App Engine"),
			Goal:           pulumi.Float64(0.9),
			CalendarPeriod: pulumi.String("DAY"),
			BasicSli: &monitoring.SloBasicSliArgs{
				Latency: &monitoring.SloBasicSliLatencyArgs{
					Threshold: pulumi.String("1s"),
				},
			},
			UserLabels: pulumi.StringMap{
				"my_key":       pulumi.String("my_value"),
				"my_other_key": pulumi.String("my_other_value"),
			},
		})
		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 @default = Gcp.Monitoring.GetAppEngineService.Invoke(new()
    {
        ModuleId = "default",
    });

    var appengSlo = new Gcp.Monitoring.Slo("appeng_slo", new()
    {
        Service = @default.Apply(@default => @default.Apply(getAppEngineServiceResult => getAppEngineServiceResult.ServiceId)),
        SloId = "ae-slo",
        DisplayName = "Test SLO for App Engine",
        Goal = 0.9,
        CalendarPeriod = "DAY",
        BasicSli = new Gcp.Monitoring.Inputs.SloBasicSliArgs
        {
            Latency = new Gcp.Monitoring.Inputs.SloBasicSliLatencyArgs
            {
                Threshold = "1s",
            },
        },
        UserLabels = 
        {
            { "my_key", "my_value" },
            { "my_other_key", "my_other_value" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.monitoring.MonitoringFunctions;
import com.pulumi.gcp.monitoring.inputs.GetAppEngineServiceArgs;
import com.pulumi.gcp.monitoring.Slo;
import com.pulumi.gcp.monitoring.SloArgs;
import com.pulumi.gcp.monitoring.inputs.SloBasicSliArgs;
import com.pulumi.gcp.monitoring.inputs.SloBasicSliLatencyArgs;
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 default = MonitoringFunctions.getAppEngineService(GetAppEngineServiceArgs.builder()
            .moduleId("default")
            .build());

        var appengSlo = new Slo("appengSlo", SloArgs.builder()
            .service(default_.serviceId())
            .sloId("ae-slo")
            .displayName("Test SLO for App Engine")
            .goal(0.9)
            .calendarPeriod("DAY")
            .basicSli(SloBasicSliArgs.builder()
                .latency(SloBasicSliLatencyArgs.builder()
                    .threshold("1s")
                    .build())
                .build())
            .userLabels(Map.ofEntries(
                Map.entry("my_key", "my_value"),
                Map.entry("my_other_key", "my_other_value")
            ))
            .build());

    }
}
resources:
  appengSlo:
    type: gcp:monitoring:Slo
    name: appeng_slo
    properties:
      service: ${default.serviceId}
      sloId: ae-slo
      displayName: Test SLO for App Engine
      goal: 0.9
      calendarPeriod: DAY
      basicSli:
        latency:
          threshold: 1s
      userLabels:
        my_key: my_value
        my_other_key: my_other_value
variables:
  default:
    fn::invoke:
      function: gcp:monitoring:getAppEngineService
      arguments:
        moduleId: default

The basicSli property provides pre-defined metrics for well-known service types like App Engine. The latency threshold defines what counts as “good service” (requests under 1 second). The goal property sets the target fraction (0.9 means 90% of requests must meet the threshold), and calendarPeriod defines the evaluation window (DAY means “since start of current day”).

Measure API latency with distribution cuts

Request-based SLIs count individual requests and classify them as good or bad based on distribution metrics.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const customsrv = new gcp.monitoring.CustomService("customsrv", {
    serviceId: "custom-srv-request-slos",
    displayName: "My Custom Service",
});
const requestBasedSlo = new gcp.monitoring.Slo("request_based_slo", {
    service: customsrv.serviceId,
    sloId: "consumed-api-slo",
    displayName: "Test SLO with request based SLI (good total ratio)",
    goal: 0.9,
    rollingPeriodDays: 30,
    requestBasedSli: {
        distributionCut: {
            distributionFilter: "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\" resource.type=\"api\"  ",
            range: {
                max: 0.5,
            },
        },
    },
});
import pulumi
import pulumi_gcp as gcp

customsrv = gcp.monitoring.CustomService("customsrv",
    service_id="custom-srv-request-slos",
    display_name="My Custom Service")
request_based_slo = gcp.monitoring.Slo("request_based_slo",
    service=customsrv.service_id,
    slo_id="consumed-api-slo",
    display_name="Test SLO with request based SLI (good total ratio)",
    goal=0.9,
    rolling_period_days=30,
    request_based_sli={
        "distribution_cut": {
            "distribution_filter": "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\" resource.type=\"api\"  ",
            "range": {
                "max": 0.5,
            },
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		customsrv, err := monitoring.NewCustomService(ctx, "customsrv", &monitoring.CustomServiceArgs{
			ServiceId:   pulumi.String("custom-srv-request-slos"),
			DisplayName: pulumi.String("My Custom Service"),
		})
		if err != nil {
			return err
		}
		_, err = monitoring.NewSlo(ctx, "request_based_slo", &monitoring.SloArgs{
			Service:           customsrv.ServiceId,
			SloId:             pulumi.String("consumed-api-slo"),
			DisplayName:       pulumi.String("Test SLO with request based SLI (good total ratio)"),
			Goal:              pulumi.Float64(0.9),
			RollingPeriodDays: pulumi.Int(30),
			RequestBasedSli: &monitoring.SloRequestBasedSliArgs{
				DistributionCut: &monitoring.SloRequestBasedSliDistributionCutArgs{
					DistributionFilter: pulumi.String("metric.type=\"serviceruntime.googleapis.com/api/request_latencies\" resource.type=\"api\"  "),
					Range: &monitoring.SloRequestBasedSliDistributionCutRangeArgs{
						Max: 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 customsrv = new Gcp.Monitoring.CustomService("customsrv", new()
    {
        ServiceId = "custom-srv-request-slos",
        DisplayName = "My Custom Service",
    });

    var requestBasedSlo = new Gcp.Monitoring.Slo("request_based_slo", new()
    {
        Service = customsrv.ServiceId,
        SloId = "consumed-api-slo",
        DisplayName = "Test SLO with request based SLI (good total ratio)",
        Goal = 0.9,
        RollingPeriodDays = 30,
        RequestBasedSli = new Gcp.Monitoring.Inputs.SloRequestBasedSliArgs
        {
            DistributionCut = new Gcp.Monitoring.Inputs.SloRequestBasedSliDistributionCutArgs
            {
                DistributionFilter = "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\" resource.type=\"api\"  ",
                Range = new Gcp.Monitoring.Inputs.SloRequestBasedSliDistributionCutRangeArgs
                {
                    Max = 0.5,
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.monitoring.CustomService;
import com.pulumi.gcp.monitoring.CustomServiceArgs;
import com.pulumi.gcp.monitoring.Slo;
import com.pulumi.gcp.monitoring.SloArgs;
import com.pulumi.gcp.monitoring.inputs.SloRequestBasedSliArgs;
import com.pulumi.gcp.monitoring.inputs.SloRequestBasedSliDistributionCutArgs;
import com.pulumi.gcp.monitoring.inputs.SloRequestBasedSliDistributionCutRangeArgs;
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) {
        var customsrv = new CustomService("customsrv", CustomServiceArgs.builder()
            .serviceId("custom-srv-request-slos")
            .displayName("My Custom Service")
            .build());

        var requestBasedSlo = new Slo("requestBasedSlo", SloArgs.builder()
            .service(customsrv.serviceId())
            .sloId("consumed-api-slo")
            .displayName("Test SLO with request based SLI (good total ratio)")
            .goal(0.9)
            .rollingPeriodDays(30)
            .requestBasedSli(SloRequestBasedSliArgs.builder()
                .distributionCut(SloRequestBasedSliDistributionCutArgs.builder()
                    .distributionFilter("metric.type=\"serviceruntime.googleapis.com/api/request_latencies\" resource.type=\"api\"  ")
                    .range(SloRequestBasedSliDistributionCutRangeArgs.builder()
                        .max(0.5)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  customsrv:
    type: gcp:monitoring:CustomService
    properties:
      serviceId: custom-srv-request-slos
      displayName: My Custom Service
  requestBasedSlo:
    type: gcp:monitoring:Slo
    name: request_based_slo
    properties:
      service: ${customsrv.serviceId}
      sloId: consumed-api-slo
      displayName: Test SLO with request based SLI (good total ratio)
      goal: 0.9
      rollingPeriodDays: 30
      requestBasedSli:
        distributionCut:
          distributionFilter: 'metric.type="serviceruntime.googleapis.com/api/request_latencies" resource.type="api"  '
          range:
            max: 0.5

The requestBasedSli property evaluates each request individually. The distributionCut specifies a metric filter (API request latencies) and a range (max 0.5 seconds). Requests within the range count as good; those outside count as bad. The rollingPeriodDays property sets a 30-day evaluation window that slides forward continuously.

Evaluate uptime checks in time windows

Windows-based SLIs divide time into fixed windows and evaluate whether each window meets quality criteria.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";

const customsrv = new gcp.monitoring.CustomService("customsrv", {
    serviceId: "custom-srv-windows-slos",
    displayName: "My Custom Service",
});
const windowsBased = new gcp.monitoring.Slo("windows_based", {
    service: customsrv.serviceId,
    displayName: "Test SLO with window based SLI",
    goal: 0.95,
    calendarPeriod: "FORTNIGHT",
    windowsBasedSli: {
        windowPeriod: "400s",
        goodBadMetricFilter: std.join({
            separator: " AND ",
            input: [
                "metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\"",
                "resource.type=\"uptime_url\"",
            ],
        }).then(invoke => invoke.result),
    },
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

customsrv = gcp.monitoring.CustomService("customsrv",
    service_id="custom-srv-windows-slos",
    display_name="My Custom Service")
windows_based = gcp.monitoring.Slo("windows_based",
    service=customsrv.service_id,
    display_name="Test SLO with window based SLI",
    goal=0.95,
    calendar_period="FORTNIGHT",
    windows_based_sli={
        "window_period": "400s",
        "good_bad_metric_filter": std.join(separator=" AND ",
            input=[
                "metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\"",
                "resource.type=\"uptime_url\"",
            ]).result,
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		customsrv, err := monitoring.NewCustomService(ctx, "customsrv", &monitoring.CustomServiceArgs{
			ServiceId:   pulumi.String("custom-srv-windows-slos"),
			DisplayName: pulumi.String("My Custom Service"),
		})
		if err != nil {
			return err
		}
		invokeJoin, err := std.Join(ctx, &std.JoinArgs{
			Separator: " AND ",
			Input: []string{
				"metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\"",
				"resource.type=\"uptime_url\"",
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = monitoring.NewSlo(ctx, "windows_based", &monitoring.SloArgs{
			Service:        customsrv.ServiceId,
			DisplayName:    pulumi.String("Test SLO with window based SLI"),
			Goal:           pulumi.Float64(0.95),
			CalendarPeriod: pulumi.String("FORTNIGHT"),
			WindowsBasedSli: &monitoring.SloWindowsBasedSliArgs{
				WindowPeriod:        pulumi.String("400s"),
				GoodBadMetricFilter: pulumi.String(invokeJoin.Result),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var customsrv = new Gcp.Monitoring.CustomService("customsrv", new()
    {
        ServiceId = "custom-srv-windows-slos",
        DisplayName = "My Custom Service",
    });

    var windowsBased = new Gcp.Monitoring.Slo("windows_based", new()
    {
        Service = customsrv.ServiceId,
        DisplayName = "Test SLO with window based SLI",
        Goal = 0.95,
        CalendarPeriod = "FORTNIGHT",
        WindowsBasedSli = new Gcp.Monitoring.Inputs.SloWindowsBasedSliArgs
        {
            WindowPeriod = "400s",
            GoodBadMetricFilter = Std.Join.Invoke(new()
            {
                Separator = " AND ",
                Input = new[]
                {
                    "metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\"",
                    "resource.type=\"uptime_url\"",
                },
            }).Apply(invoke => invoke.Result),
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.monitoring.CustomService;
import com.pulumi.gcp.monitoring.CustomServiceArgs;
import com.pulumi.gcp.monitoring.Slo;
import com.pulumi.gcp.monitoring.SloArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.JoinArgs;
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) {
        var customsrv = new CustomService("customsrv", CustomServiceArgs.builder()
            .serviceId("custom-srv-windows-slos")
            .displayName("My Custom Service")
            .build());

        var windowsBased = new Slo("windowsBased", SloArgs.builder()
            .service(customsrv.serviceId())
            .displayName("Test SLO with window based SLI")
            .goal(0.95)
            .calendarPeriod("FORTNIGHT")
            .windowsBasedSli(SloWindowsBasedSliArgs.builder()
                .windowPeriod("400s")
                .goodBadMetricFilter(StdFunctions.join(JoinArgs.builder()
                    .separator(" AND ")
                    .input(                    
                        "metric.type=\"monitoring.googleapis.com/uptime_check/check_passed\"",
                        "resource.type=\"uptime_url\"")
                    .build()).result())
                .build())
            .build());

    }
}
resources:
  customsrv:
    type: gcp:monitoring:CustomService
    properties:
      serviceId: custom-srv-windows-slos
      displayName: My Custom Service
  windowsBased:
    type: gcp:monitoring:Slo
    name: windows_based
    properties:
      service: ${customsrv.serviceId}
      displayName: Test SLO with window based SLI
      goal: 0.95
      calendarPeriod: FORTNIGHT
      windowsBasedSli:
        windowPeriod: 400s
        goodBadMetricFilter:
          fn::invoke:
            function: std:join
            arguments:
              separator: ' AND '
              input:
                - metric.type="monitoring.googleapis.com/uptime_check/check_passed"
                - resource.type="uptime_url"
            return: result

The windowsBasedSli property divides time into 400-second windows. The goodBadMetricFilter specifies which metric to evaluate (uptime check results). Each window where the metric indicates success counts as a good window. The goal (0.95) means 95% of windows must be good.

Monitor mean latency within time windows

Some SLOs track whether average metric values stay within acceptable ranges during each time window.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";

const customsrv = new gcp.monitoring.CustomService("customsrv", {
    serviceId: "custom-srv-windows-slos",
    displayName: "My Custom Service",
});
const windowsBased = new gcp.monitoring.Slo("windows_based", {
    service: customsrv.serviceId,
    displayName: "Test SLO with window based SLI",
    goal: 0.9,
    rollingPeriodDays: 20,
    windowsBasedSli: {
        windowPeriod: "600s",
        metricMeanInRange: {
            timeSeries: std.join({
                separator: " AND ",
                input: [
                    "metric.type=\"agent.googleapis.com/cassandra/client_request/latency/95p\"",
                    "resource.type=\"gce_instance\"",
                ],
            }).then(invoke => invoke.result),
            range: {
                max: 5,
            },
        },
    },
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

customsrv = gcp.monitoring.CustomService("customsrv",
    service_id="custom-srv-windows-slos",
    display_name="My Custom Service")
windows_based = gcp.monitoring.Slo("windows_based",
    service=customsrv.service_id,
    display_name="Test SLO with window based SLI",
    goal=0.9,
    rolling_period_days=20,
    windows_based_sli={
        "window_period": "600s",
        "metric_mean_in_range": {
            "time_series": std.join(separator=" AND ",
                input=[
                    "metric.type=\"agent.googleapis.com/cassandra/client_request/latency/95p\"",
                    "resource.type=\"gce_instance\"",
                ]).result,
            "range": {
                "max": 5,
            },
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		customsrv, err := monitoring.NewCustomService(ctx, "customsrv", &monitoring.CustomServiceArgs{
			ServiceId:   pulumi.String("custom-srv-windows-slos"),
			DisplayName: pulumi.String("My Custom Service"),
		})
		if err != nil {
			return err
		}
		invokeJoin, err := std.Join(ctx, &std.JoinArgs{
			Separator: " AND ",
			Input: []string{
				"metric.type=\"agent.googleapis.com/cassandra/client_request/latency/95p\"",
				"resource.type=\"gce_instance\"",
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = monitoring.NewSlo(ctx, "windows_based", &monitoring.SloArgs{
			Service:           customsrv.ServiceId,
			DisplayName:       pulumi.String("Test SLO with window based SLI"),
			Goal:              pulumi.Float64(0.9),
			RollingPeriodDays: pulumi.Int(20),
			WindowsBasedSli: &monitoring.SloWindowsBasedSliArgs{
				WindowPeriod: pulumi.String("600s"),
				MetricMeanInRange: &monitoring.SloWindowsBasedSliMetricMeanInRangeArgs{
					TimeSeries: pulumi.String(invokeJoin.Result),
					Range: &monitoring.SloWindowsBasedSliMetricMeanInRangeRangeArgs{
						Max: pulumi.Float64(5),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var customsrv = new Gcp.Monitoring.CustomService("customsrv", new()
    {
        ServiceId = "custom-srv-windows-slos",
        DisplayName = "My Custom Service",
    });

    var windowsBased = new Gcp.Monitoring.Slo("windows_based", new()
    {
        Service = customsrv.ServiceId,
        DisplayName = "Test SLO with window based SLI",
        Goal = 0.9,
        RollingPeriodDays = 20,
        WindowsBasedSli = new Gcp.Monitoring.Inputs.SloWindowsBasedSliArgs
        {
            WindowPeriod = "600s",
            MetricMeanInRange = new Gcp.Monitoring.Inputs.SloWindowsBasedSliMetricMeanInRangeArgs
            {
                TimeSeries = Std.Join.Invoke(new()
                {
                    Separator = " AND ",
                    Input = new[]
                    {
                        "metric.type=\"agent.googleapis.com/cassandra/client_request/latency/95p\"",
                        "resource.type=\"gce_instance\"",
                    },
                }).Apply(invoke => invoke.Result),
                Range = new Gcp.Monitoring.Inputs.SloWindowsBasedSliMetricMeanInRangeRangeArgs
                {
                    Max = 5,
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.monitoring.CustomService;
import com.pulumi.gcp.monitoring.CustomServiceArgs;
import com.pulumi.gcp.monitoring.Slo;
import com.pulumi.gcp.monitoring.SloArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliMetricMeanInRangeArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliMetricMeanInRangeRangeArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.JoinArgs;
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) {
        var customsrv = new CustomService("customsrv", CustomServiceArgs.builder()
            .serviceId("custom-srv-windows-slos")
            .displayName("My Custom Service")
            .build());

        var windowsBased = new Slo("windowsBased", SloArgs.builder()
            .service(customsrv.serviceId())
            .displayName("Test SLO with window based SLI")
            .goal(0.9)
            .rollingPeriodDays(20)
            .windowsBasedSli(SloWindowsBasedSliArgs.builder()
                .windowPeriod("600s")
                .metricMeanInRange(SloWindowsBasedSliMetricMeanInRangeArgs.builder()
                    .timeSeries(StdFunctions.join(JoinArgs.builder()
                        .separator(" AND ")
                        .input(                        
                            "metric.type=\"agent.googleapis.com/cassandra/client_request/latency/95p\"",
                            "resource.type=\"gce_instance\"")
                        .build()).result())
                    .range(SloWindowsBasedSliMetricMeanInRangeRangeArgs.builder()
                        .max(5.0)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  customsrv:
    type: gcp:monitoring:CustomService
    properties:
      serviceId: custom-srv-windows-slos
      displayName: My Custom Service
  windowsBased:
    type: gcp:monitoring:Slo
    name: windows_based
    properties:
      service: ${customsrv.serviceId}
      displayName: Test SLO with window based SLI
      goal: 0.9
      rollingPeriodDays: 20
      windowsBasedSli:
        windowPeriod: 600s
        metricMeanInRange:
          timeSeries:
            fn::invoke:
              function: std:join
              arguments:
                separator: ' AND '
                input:
                  - metric.type="agent.googleapis.com/cassandra/client_request/latency/95p"
                  - resource.type="gce_instance"
              return: result
          range:
            max: 5

The metricMeanInRange property calculates the mean value of the specified metric (Cassandra 95th percentile latency) within each window. If the mean stays below the range maximum (5ms), the window counts as good. This differs from counting individual requests; it evaluates aggregate behavior per window.

Apply ratio thresholds to distribution cuts

Complex SLOs sometimes evaluate whether the ratio of good to total requests within each window exceeds a threshold.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";

const customsrv = new gcp.monitoring.CustomService("customsrv", {
    serviceId: "custom-srv-windows-slos",
    displayName: "My Custom Service",
});
const windowsBased = new gcp.monitoring.Slo("windows_based", {
    service: customsrv.serviceId,
    displayName: "Test SLO with window based SLI",
    goal: 0.9,
    rollingPeriodDays: 20,
    windowsBasedSli: {
        windowPeriod: "100s",
        goodTotalRatioThreshold: {
            threshold: 0.1,
            performance: {
                distributionCut: {
                    distributionFilter: std.join({
                        separator: " AND ",
                        input: [
                            "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\"",
                            "resource.type=\"consumed_api\"",
                        ],
                    }).then(invoke => invoke.result),
                    range: {
                        min: 1,
                        max: 9,
                    },
                },
            },
        },
    },
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std

customsrv = gcp.monitoring.CustomService("customsrv",
    service_id="custom-srv-windows-slos",
    display_name="My Custom Service")
windows_based = gcp.monitoring.Slo("windows_based",
    service=customsrv.service_id,
    display_name="Test SLO with window based SLI",
    goal=0.9,
    rolling_period_days=20,
    windows_based_sli={
        "window_period": "100s",
        "good_total_ratio_threshold": {
            "threshold": 0.1,
            "performance": {
                "distribution_cut": {
                    "distribution_filter": std.join(separator=" AND ",
                        input=[
                            "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\"",
                            "resource.type=\"consumed_api\"",
                        ]).result,
                    "range": {
                        "min": 1,
                        "max": 9,
                    },
                },
            },
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/monitoring"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		customsrv, err := monitoring.NewCustomService(ctx, "customsrv", &monitoring.CustomServiceArgs{
			ServiceId:   pulumi.String("custom-srv-windows-slos"),
			DisplayName: pulumi.String("My Custom Service"),
		})
		if err != nil {
			return err
		}
		invokeJoin, err := std.Join(ctx, &std.JoinArgs{
			Separator: " AND ",
			Input: []string{
				"metric.type=\"serviceruntime.googleapis.com/api/request_latencies\"",
				"resource.type=\"consumed_api\"",
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = monitoring.NewSlo(ctx, "windows_based", &monitoring.SloArgs{
			Service:           customsrv.ServiceId,
			DisplayName:       pulumi.String("Test SLO with window based SLI"),
			Goal:              pulumi.Float64(0.9),
			RollingPeriodDays: pulumi.Int(20),
			WindowsBasedSli: &monitoring.SloWindowsBasedSliArgs{
				WindowPeriod: pulumi.String("100s"),
				GoodTotalRatioThreshold: &monitoring.SloWindowsBasedSliGoodTotalRatioThresholdArgs{
					Threshold: pulumi.Float64(0.1),
					Performance: &monitoring.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceArgs{
						DistributionCut: &monitoring.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutArgs{
							DistributionFilter: pulumi.String(invokeJoin.Result),
							Range: &monitoring.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutRangeArgs{
								Min: pulumi.Float64(1),
								Max: pulumi.Float64(9),
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var customsrv = new Gcp.Monitoring.CustomService("customsrv", new()
    {
        ServiceId = "custom-srv-windows-slos",
        DisplayName = "My Custom Service",
    });

    var windowsBased = new Gcp.Monitoring.Slo("windows_based", new()
    {
        Service = customsrv.ServiceId,
        DisplayName = "Test SLO with window based SLI",
        Goal = 0.9,
        RollingPeriodDays = 20,
        WindowsBasedSli = new Gcp.Monitoring.Inputs.SloWindowsBasedSliArgs
        {
            WindowPeriod = "100s",
            GoodTotalRatioThreshold = new Gcp.Monitoring.Inputs.SloWindowsBasedSliGoodTotalRatioThresholdArgs
            {
                Threshold = 0.1,
                Performance = new Gcp.Monitoring.Inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceArgs
                {
                    DistributionCut = new Gcp.Monitoring.Inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutArgs
                    {
                        DistributionFilter = Std.Join.Invoke(new()
                        {
                            Separator = " AND ",
                            Input = new[]
                            {
                                "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\"",
                                "resource.type=\"consumed_api\"",
                            },
                        }).Apply(invoke => invoke.Result),
                        Range = new Gcp.Monitoring.Inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutRangeArgs
                        {
                            Min = 1,
                            Max = 9,
                        },
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.monitoring.CustomService;
import com.pulumi.gcp.monitoring.CustomServiceArgs;
import com.pulumi.gcp.monitoring.Slo;
import com.pulumi.gcp.monitoring.SloArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliGoodTotalRatioThresholdArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutArgs;
import com.pulumi.gcp.monitoring.inputs.SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutRangeArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.JoinArgs;
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) {
        var customsrv = new CustomService("customsrv", CustomServiceArgs.builder()
            .serviceId("custom-srv-windows-slos")
            .displayName("My Custom Service")
            .build());

        var windowsBased = new Slo("windowsBased", SloArgs.builder()
            .service(customsrv.serviceId())
            .displayName("Test SLO with window based SLI")
            .goal(0.9)
            .rollingPeriodDays(20)
            .windowsBasedSli(SloWindowsBasedSliArgs.builder()
                .windowPeriod("100s")
                .goodTotalRatioThreshold(SloWindowsBasedSliGoodTotalRatioThresholdArgs.builder()
                    .threshold(0.1)
                    .performance(SloWindowsBasedSliGoodTotalRatioThresholdPerformanceArgs.builder()
                        .distributionCut(SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutArgs.builder()
                            .distributionFilter(StdFunctions.join(JoinArgs.builder()
                                .separator(" AND ")
                                .input(                                
                                    "metric.type=\"serviceruntime.googleapis.com/api/request_latencies\"",
                                    "resource.type=\"consumed_api\"")
                                .build()).result())
                            .range(SloWindowsBasedSliGoodTotalRatioThresholdPerformanceDistributionCutRangeArgs.builder()
                                .min(1.0)
                                .max(9.0)
                                .build())
                            .build())
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  customsrv:
    type: gcp:monitoring:CustomService
    properties:
      serviceId: custom-srv-windows-slos
      displayName: My Custom Service
  windowsBased:
    type: gcp:monitoring:Slo
    name: windows_based
    properties:
      service: ${customsrv.serviceId}
      displayName: Test SLO with window based SLI
      goal: 0.9
      rollingPeriodDays: 20
      windowsBasedSli:
        windowPeriod: 100s
        goodTotalRatioThreshold:
          threshold: 0.1
          performance:
            distributionCut:
              distributionFilter:
                fn::invoke:
                  function: std:join
                  arguments:
                    separator: ' AND '
                    input:
                      - metric.type="serviceruntime.googleapis.com/api/request_latencies"
                      - resource.type="consumed_api"
                  return: result
              range:
                min: 1
                max: 9

The goodTotalRatioThreshold property combines distribution analysis with window-based evaluation. Within each 100-second window, it calculates what fraction of requests fall within the distribution range (1-9ms). If that fraction exceeds the threshold (0.1), the window counts as good. The performance block defines how to classify individual requests using distributionCut.

Beyond these examples

These snippets focus on specific SLO-level features: basic SLIs for well-known services, request-based and windows-based evaluation, and distribution cuts and metric aggregations. They’re intentionally minimal rather than full monitoring solutions.

The examples reference pre-existing infrastructure such as monitoring services (App Engine, custom services) and metric data sources (API latencies, uptime checks). They focus on configuring the SLO rather than provisioning the underlying services.

To keep things focused, common SLO patterns are omitted, including:

  • User labels for organization (userLabels)
  • Calendar vs rolling period tradeoffs
  • Metric sum aggregations (metricSumInRange)
  • Alert policy integration

These omissions are intentional: the goal is to illustrate how each SLO evaluation method is wired, not provide drop-in monitoring modules. See the Monitoring SLO resource reference for all available configuration options.

Let's configure GCP Service-Level Objectives

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Configuration
What properties can't I change after creating an SLO?
The project, service, and sloId properties are immutable and cannot be changed after creation.
Can I use multiple SLI types in one SLO?
No, you must choose exactly one of basicSli, requestBasedSli, or windowsBasedSli for each SLO.
SLI Selection
Which SLI type should I use for my service?
Use basicSli for well-known service types with pre-defined metrics (like App Engine latency), requestBasedSli for counting atomic service units directly (like API request success rates), or windowsBasedSli for time-window-based criteria (like uptime checks or metric aggregations over time windows).
Goal & Period Configuration
What are the valid goal values for an SLO?
The goal must be greater than 0 and less than or equal to 0.999. For example, use 0.9 for 90% or 0.995 for 99.5%.
How do I configure the evaluation period for my SLO?
You can use either calendarPeriod (DAY, WEEK, FORTNIGHT, or MONTH) for calendar-based evaluation, or rollingPeriodDays (1-30 days) for rolling window evaluation. Choose one approach, not both.
Labels & Metadata
What are the constraints for user labels?
You can add up to 64 label entries. Each key and value is limited to 63 Unicode characters or 128 bytes. Labels can contain only lowercase letters, numerals, underscores, and dashes, and keys must begin with a letter.

Using a different cloud?

Explore monitoring guides for other cloud providers: