If the objective says 95% of checkout requests must finish within 300 milliseconds, add 0.3 as an explicit histogram boundary. Without it, coarse buckets can prevent you from counting exactly how many requests met the threshold.

A histogram does not retain every recorded duration. It groups measurements into buckets. Suppose the available boundaries jump from 0.25 to 0.5 seconds. The resulting bucket tells you how many requests took more than 250 and at most 500 milliseconds, but it cannot separate a 280-millisecond success from a 450-millisecond breach.

Start with the question the metric needs to answer. A generic sequence of round numbers may miss the one threshold that matters.

Put the objective into the configuration

OpenTelemetry recommends seconds for duration instruments. The product requirement can still say 300 milliseconds, while the metric records 0.3 seconds:

using System.Diagnostics.Metrics;

public static class CheckoutMetrics
{
    public const string MeterName = "Checkout.Api";

    private static readonly Meter Meter = new(MeterName);

    private static readonly Histogram<double> Duration =
        Meter.CreateHistogram<double>(
            "checkout.duration",
            unit: "s",
            description: "End-to-end checkout duration in seconds.");

    public static void Record(TimeSpan elapsed) =>
        Duration.Record(elapsed.TotalSeconds);
}

Register the meter and its explicit boundaries at the hosting edge:

using OpenTelemetry.Metrics;

builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddMeter(CheckoutMetrics.MeterName)
        .AddView(
            "checkout.duration",
            new ExplicitBucketHistogramConfiguration
            {
                Boundaries = new double[]
                {
                    0.05, 0.1, 0.2, 0.3, 0.5, 1.0, 2.5
                }
            })
        .AddOtlpExporter());

OpenTelemetry uses the configured values as upper boundaries. In the histogram itself, the bucket ending at 0.3 contains measurements greater than 0.2 and less than or equal to 0.3 seconds. That individual bucket is not the numerator for the objective.

A backend that exposes cumulative histogram buckets can use the cumulative count through 0.3, divided by the total count, to calculate the share of requests that met the latency threshold. The query still needs the right request population and evaluation window.

For this objective, the useful number is the fraction of requests that finished within 300 milliseconds. There is no need to estimate p95 and compare that estimate with the threshold. With histogram data, percentile estimation may interpolate between buckets. The explicit boundary at 0.3 keeps the threshold intact.

Add diagnostic resolution deliberately

Put the service-objective boundary in place first. Add nearby boundaries when they answer operational questions:

  • 0.2 shows how much traffic has comfortable headroom.
  • 0.3 preserves the exact threshold needed to calculate compliance.
  • 0.5 shows a moderate breach.
  • 1.0 and 2.5 separate slow requests from severe outliers.

Those values are examples. A model generation endpoint may run for several seconds, while a cache lookup may finish in a few milliseconds. Both duration metrics should still use seconds, with boundaries that fit their own latency ranges.

Every extra boundary adds some cost. More buckets increase telemetry volume and backend work, especially across many attribute combinations. Add resolution when it supports a product threshold, an alert, or a concrete debugging decision.

Know which histogram you export

This advice applies to explicit-bucket histograms. Base-2 exponential histograms determine their boundaries dynamically from their scale and size configuration. They cover a wide measurement range without a fixed list of explicit boundaries, and they do not use ExplicitBucketHistogramConfiguration.

Aggregation may change after the application emits the metric. An SDK view, collector transformation, exporter, or monitoring backend can alter the final histogram representation. Inspect the exported metric and confirm that it still contains the boundary required by the objective.

Before building the alert, confirm that the exported metric uses seconds and still has a boundary at 0.3. Then calculate compliance over the SLO window and the intended request population. A dashboard cannot recover exact compliance at a threshold that the aggregation did not preserve.