<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Manage advanced systems on Grafana Labs</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/</link><description>Recent content in Manage advanced systems on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/tempo/v3.0.x/operations/manage-advanced-systems/index.xml" rel="self" type="application/rss+xml"/><item><title>Enable multi-tenancy</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/</guid><content><![CDATA[&lt;h1 id=&#34;enable-multi-tenancy&#34;&gt;Enable multi-tenancy&lt;/h1&gt;
&lt;p&gt;Tempo is a multi-tenant distributed tracing backend.
Tempo uses the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header to enforce multi-tenancy in Tempo and Grafana Enterprise Traces.
It is set to the tenant (or &amp;ldquo;organization&amp;rdquo;) name.
It is used for scoped writes (ingest) so that each span is stored under its specified tenant, and scoped reads so that queries return only that tenant&amp;rsquo;s data.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in setting up multi-tenancy, consult the &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/example/docker-compose/multitenant&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;multi-tenant example&lt;/a&gt;
in the repository. This example uses the following settings to achieve multi-tenancy in Tempo.&lt;/p&gt;
&lt;h2 id=&#34;tenant-ids&#34;&gt;Tenant IDs&lt;/h2&gt;
&lt;p&gt;Tenant IDs are transmitted to Tempo via the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; HTTP header. This header must be included in all requests to Tempo when multi-tenancy is enabled.&lt;/p&gt;
&lt;p&gt;Multi-tenancy on ingestion is supported with both gRPC and HTTP for OTLP (OpenTelemetry Protocol). You can add the header in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenTelemetry Collector configuration&lt;/li&gt;
&lt;li&gt;Grafana Alloy configuration&lt;/li&gt;
&lt;li&gt;Any HTTP/gRPC client using &lt;code&gt;curl&lt;/code&gt; or other relevant tools&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;example-alloy-configuration&#34;&gt;Example Alloy configuration&lt;/h2&gt;
&lt;p&gt;The following example shows how to configure Grafana Alloy to send traces with a tenant ID.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;otelcol.exporter.otlphttp &amp;#34;tempo&amp;#34; {
    // Define the client for exporting.
    client {
        // Send the X-Scope-OrgID header to the Tempo instance for multi-tenancy (tenant 1234).
        headers = {
            &amp;#34;X-Scope-OrgID&amp;#34; = &amp;#34;1234&amp;#34;,
        }

        // Send to the locally running Tempo instance, on port 4318 (OTLP HTTP).
        endpoint = &amp;#34;http://tempo:4318&amp;#34;

        // Configure TLS settings for communicating with the endpoint.
        tls {
            // The connection is insecure.
            insecure = true
            // Do not verify TLS certificates when connecting.
            insecure_skip_verify = true
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configure-multi-tenancy&#34;&gt;Configure multi-tenancy&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Configure the OpenTelemetry Collector to attach the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header on push:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;exporters:
  otlp:
    headers:
      x-scope-orgid: foo-bar-baz&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the Tempo data source in Grafana to pass the tenant with the same header:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;- name: Tempo-Multitenant
  jsonData:
    httpHeaderName1: &amp;#34;X-Scope-OrgID&amp;#34;
  secureJsonData:
    httpHeaderValue1: &amp;#34;foo-bar-baz&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable multi-tenancy on the Tempo backend by setting the following configuration value on all Tempo components:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;multitenancy_enabled: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;or from the command line:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;tempo --multitenancy.enabled=true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This option forces all Tempo components to require the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;configure-per-tenant-settings&#34;&gt;Configure per-tenant settings&lt;/h2&gt;
&lt;p&gt;After you enable multi-tenancy, you can customize settings on a per-tenant basis using runtime overrides.
This is useful when different tenants have different requirements, for example varying block retention periods or ingestion limits.&lt;/p&gt;
&lt;p&gt;This configuration works for both Tempo 2.x and Tempo 3.x architectures.
If you are upgrading from Tempo 2.x, refer to the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/set-up-for-tracing/setup-tempo/migrate-to-3/&#34;&gt;Tempo 3.0 migration guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To configure per-tenant overrides, create a separate overrides file and reference it from your main Tempo configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;# tempo.yaml
overrides:
  per_tenant_override_config: /conf/overrides.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Define tenant-specific settings in the &lt;code&gt;overrides.yaml&lt;/code&gt; file.
The following example sets different block retention periods and ingestion limits for two tenants:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;# overrides.yaml
overrides:
  &amp;#34;tenant-a&amp;#34;:
    compaction:
      block_retention: 24h
    ingestion:
      burst_size_bytes: 20000000
      rate_limit_bytes: 4000000
      max_traces_per_user: 10000
    global:
      max_bytes_per_trace: 30000000
    metrics_generator:
      collection_interval: 15s
      ring_size: 2
      max_active_series: 5000
      processors:
        - span-metrics
        - service-graphs
      forwarder:
        queue_size: 5000
        workers: 3
  &amp;#34;tenant-b&amp;#34;:
    compaction:
      block_retention: 48h
    ingestion:
      burst_size_bytes: 20000000
      rate_limit_bytes: 4000000
      max_traces_per_user: 10000
    global:
      max_bytes_per_trace: 30000000
    metrics_generator:
      ring_size: 2
      max_active_series: 100000
      processors: []
      forwarder:
        queue_size: 5000
        workers: 3&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;When using per-tenant overrides, you must set every field you want to preserve.
Tempo replaces unset fields with zero values, not with the defaults from your main configuration.
Omitting a field can lead to unexpected behavior, such as a &lt;code&gt;0s&lt;/code&gt; retention effectively disabling block retention for that tenant.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The overrides file is dynamically loaded, so you can update it at runtime without restarting Tempo.&lt;/p&gt;
&lt;p&gt;For the full list of available override fields, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#overrides&#34;&gt;Overrides&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="enable-multi-tenancy">Enable multi-tenancy&lt;/h1>
&lt;p>Tempo is a multi-tenant distributed tracing backend.
Tempo uses the &lt;code>X-Scope-OrgID&lt;/code> header to enforce multi-tenancy in Tempo and Grafana Enterprise Traces.
It is set to the tenant (or &amp;ldquo;organization&amp;rdquo;) name.
It is used for scoped writes (ingest) so that each span is stored under its specified tenant, and scoped reads so that queries return only that tenant&amp;rsquo;s data.&lt;/p></description></item><item><title>Cross-tenant query federation</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/cross_tenant_query/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/cross_tenant_query/</guid><content><![CDATA[&lt;h1 id=&#34;cross-tenant-query-federation&#34;&gt;Cross-tenant query federation&lt;/h1&gt;
&lt;p&gt;Cross-tenant query federation lets you run a single query across multiple tenants at the same time, instead of repeating the same query for each tenant individually.
This is useful when you operate many teams or environments and need to troubleshoot, compare behavior, or enforce governance consistently across them.&lt;/p&gt;
&lt;h2 id=&#34;supported-operations&#34;&gt;Supported operations&lt;/h2&gt;
&lt;p&gt;Tempo supports multi-tenant queries for search, search-tags, and trace-by-ID search operations.
TraceQL metrics queries (for example, query range and instant endpoints that use TraceQLMetrics) also support cross-tenant queries.&lt;/p&gt;
&lt;p&gt;These operations can be federated across multiple tenants when you specify more than one tenant ID in the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header.&lt;/p&gt;
&lt;p&gt;To perform multi-tenant queries, send tenant IDs separated by a &lt;code&gt;|&lt;/code&gt; character in the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header, for example, &lt;code&gt;foo|bar&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;enable-cross-tenant-query&#34;&gt;Enable cross-tenant query&lt;/h2&gt;
&lt;p&gt;By default, cross-tenant query is enabled and can be controlled using &lt;code&gt;multi_tenant_queries_enabled&lt;/code&gt; configuration setting.&lt;/p&gt;
&lt;p&gt;This setting is a no-op unless &lt;code&gt;multitenancy_enabled: true&lt;/code&gt; is enabled in the cluster configuration.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;query_frontend:
  multi_tenant_queries_enabled: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For more information on configuration options, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/&#34;&gt;Enable multi-tenancy&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;traceql-queries&#34;&gt;TraceQL queries&lt;/h2&gt;
&lt;p&gt;Queries performed using the cross-tenant configured data source, in either &lt;strong&gt;Explore&lt;/strong&gt; or inside of dashboards,
are performed across all the tenants that you specified in the &lt;strong&gt;X-Scope-OrgID&lt;/strong&gt; header.&lt;/p&gt;
&lt;p&gt;TraceQL queries that compare multiple spansets may not correctly return all traces in a cross-tenant query. For instance,&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;{ span.attr1 = &amp;#34;bar&amp;#34; } &amp;amp;&amp;amp; { span.attr2 = &amp;#34;foo&amp;#34; }&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;TraceQL evaluates a contiguously stored trace.
If these two conditions are satisfied in separate tenants, then Tempo doesn&amp;rsquo;t correctly return the trace.&lt;/p&gt;
&lt;h2 id=&#34;tenant-ids-in-cross-tenant-queries&#34;&gt;Tenant IDs in cross-tenant queries&lt;/h2&gt;
&lt;p&gt;Tempo uses the same &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header for cross-tenant queries as for single-tenant queries.
To query multiple tenants, specify tenant IDs separated by a &lt;code&gt;|&lt;/code&gt; character in the header.&lt;/p&gt;
&lt;p&gt;When multiple tenant IDs are specified, Tempo normalizes them by sorting and removing duplicate tenant IDs.
For example, &lt;code&gt;bar|foo|bar&lt;/code&gt; is normalized to &lt;code&gt;bar|foo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The following example shows an HTTP request that performs a cross-tenant query across the &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; tenants:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -H &amp;#34;X-Scope-OrgID: foo|bar&amp;#34; \
  &amp;#34;http://tempo-query:3200/api/traces/search?limit=20&amp;amp;query={ service.name = \&amp;#34;checkout\&amp;#34; }&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For tenant ID format, allowed characters, and reserved values, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/tenant-ids/&#34;&gt;Tenant IDs&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;security-considerations&#34;&gt;Security considerations&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header should be set by a trusted reverse proxy, not by client applications. Tempo assumes that clients setting &lt;code&gt;X-Scope-OrgID&lt;/code&gt; are trusted, and the responsibility of populating this value should be handled by your authenticating reverse proxy.&lt;/p&gt;
&lt;p&gt;Allowing clients to set the tenant ID directly can lead to unauthorized access to other tenants&amp;rsquo; data. A malicious client could change the tenant ID in the header to access traces from other tenants.&lt;/p&gt;
&lt;p&gt;For more information about setting up authentication and reverse proxies, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/authentication/&#34;&gt;Manage authentication&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="cross-tenant-query-federation">Cross-tenant query federation&lt;/h1>
&lt;p>Cross-tenant query federation lets you run a single query across multiple tenants at the same time, instead of repeating the same query for each tenant individually.
This is useful when you operate many teams or environments and need to troubleshoot, compare behavior, or enforce governance consistently across them.&lt;/p></description></item><item><title>User-configurable overrides</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/user-configurable-overrides/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/user-configurable-overrides/</guid><content><![CDATA[&lt;h1 id=&#34;user-configurable-overrides&#34;&gt;User-configurable overrides&lt;/h1&gt;
&lt;p&gt;User-configurable overrides in Tempo let you change overrides for your tenant using an API.
Instead of modifying a file or Kubernetes &lt;code&gt;configmap&lt;/code&gt;, you (and other services relying on Tempo) can use this API to
modify the overrides directly.&lt;/p&gt;
&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;User-configurable overrides are stored in an object store bucket managed by Tempo.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../user-configurable-overrides-architecture.svg&#34;
  alt=&#34;user-configurable-overrides-architecture.svg&#34;/&gt;&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;We recommend using a different bucket for overrides and traces storage, but they can share a bucket if needed.
When sharing a bucket, make sure any lifecycle rules are scoped correctly to not remove data of user-configurable
overrides module.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Overrides of every tenant are stored at &lt;code&gt;/{tenant name}/overrides.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;overrides/
├── 1/
│   └── overrides.json
└── 2/
    └── overrides.json&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Tempo regularly polls this bucket and keeps a copy of the limits in-memory. When requesting the overrides for a tenant,
the overrides module:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checks this override is set in the user-configurable overrides, if so return that value.&lt;/li&gt;
&lt;li&gt;Checks if this override is set in the runtime configuration (&lt;code&gt;configmap&lt;/code&gt;), if so return that value.&lt;/li&gt;
&lt;li&gt;Returns the default value.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;supported-fields&#34;&gt;Supported fields&lt;/h3&gt;
&lt;p&gt;User-configurable overrides are designed to be a subset of the runtime overrides. Refer
to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#overrides&#34;&gt;Overrides&lt;/a&gt; for information about all
overrides.
When you set a field in both the user-configurable overrides and the runtime overrides, the value from the
user-configurable overrides takes priority.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;In Tempo 2.x, &lt;code&gt;metrics_generator.processors&lt;/code&gt; user-configurable override field is OR-merged with the runtime overrides list.&lt;/p&gt;
&lt;p&gt;In Tempo 3.0, if &lt;code&gt;processors&lt;/code&gt; is set in user-configurable overrides, that will override the runtime &lt;code&gt;metrics_generator.processors&lt;/code&gt; config. Setting &lt;code&gt;processors: []&lt;/code&gt; in user-configurable overrides disables all processors for the tenant.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;



&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;The &lt;code&gt;local-blocks&lt;/code&gt; processor was removed in Tempo 3.0. TraceQL metrics queries on recent data are now served by the live-store instead. If your overrides reference &lt;code&gt;local-blocks&lt;/code&gt;, remove it before upgrading.
For details, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/metrics-from-traces/metrics-generator/&#34;&gt;Metrics generator&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;


&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;[forwarders: &amp;lt;list of strings&amp;gt;]

cost_attribution:
  [dimensions: &amp;lt;map string to string&amp;gt;]

metrics_generator:

  [processors: &amp;lt;list of strings&amp;gt;]
  [collection_interval: &amp;lt;duration&amp;gt;]
  [trace_id_label_name: &amp;lt;string&amp;gt;]
  [ingestion_time_range_slack: &amp;lt;duration&amp;gt;]
  [disable_collection: &amp;lt;bool&amp;gt; | default = false]
  [generate_native_histograms: &amp;lt;classic|native|both&amp;gt; | default = classic]
  [native_histogram_max_bucket_number: &amp;lt;int&amp;gt; | default = 100]
  [native_histogram_bucket_factor: &amp;lt;float&amp;gt; | default = 1.1]
  [native_histogram_min_reset_duration: &amp;lt;duration&amp;gt; | default = 15m]
  [span_name_sanitization: &amp;lt;string&amp;gt;]

  processor:

    service_graphs:
      [histogram_buckets: &amp;lt;list of float&amp;gt;]
      [dimensions: &amp;lt;list of string&amp;gt;]
      [peer_attributes: &amp;lt;list of string&amp;gt;]
      [enable_client_server_prefix: &amp;lt;bool&amp;gt;]
      [enable_messaging_system_latency_histogram: &amp;lt;bool&amp;gt;]
      [enable_virtual_node_label: &amp;lt;bool&amp;gt;]
      [span_multiplier_key: &amp;lt;string&amp;gt;]
      [enable_tracestate_span_multiplier: &amp;lt;bool&amp;gt;]
      [filter_policies: [
        [
          include/include_any/exclude:
            match_type: &amp;lt;string&amp;gt; # options: strict, regex
            attributes:
              - key: &amp;lt;string&amp;gt;
                value: &amp;lt;any&amp;gt;
        ]
      ]]
    span_metrics:
      [histogram_buckets: &amp;lt;list of float&amp;gt;]
      [dimensions: &amp;lt;list of string&amp;gt;]
      [dimension_mappings: &amp;lt;list of mappings {name: &amp;lt;string&amp;gt;, source_labels: &amp;lt;list of string&amp;gt;, join: &amp;lt;string&amp;gt;}&amp;gt;]
      [intrinsic_dimensions: &amp;lt;map string to bool&amp;gt;]
      [filter_policies: [
        [
          include/include_any/exclude:
            match_type: &amp;lt;string&amp;gt; # options: strict, regex
            attributes:
              - key: &amp;lt;string&amp;gt;
                value: &amp;lt;any&amp;gt;
        ]
      ]]
      [enable_target_info: &amp;lt;bool&amp;gt;]
      [target_info_excluded_dimensions: &amp;lt;list of string&amp;gt;]
      [enable_instance_label: &amp;lt;bool&amp;gt;]
      [span_multiplier_key: &amp;lt;string&amp;gt;]
      [enable_tracestate_span_multiplier: &amp;lt;bool&amp;gt;]

    host_info:
      [host_identifiers: &amp;lt;list of string&amp;gt;]
      [metric_name: &amp;lt;string&amp;gt;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;filter-policy-validation&#34;&gt;Filter policy validation&lt;/h3&gt;
&lt;p&gt;Filter policies submitted through this API are fully validated. Tempo checks that attribute keys are valid TraceQL identifiers, only &lt;code&gt;resource&lt;/code&gt; and &lt;code&gt;span&lt;/code&gt; scopes are supported, regular expression patterns compile, and intrinsic values (&lt;code&gt;kind&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;) use recognized values. Invalid policies are rejected with a descriptive error.&lt;/p&gt;
&lt;p&gt;For the complete list of validation rules and supported values, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/metrics-from-traces/span-metrics/span-metrics-metrics-generator/#filtering&#34;&gt;Filtering&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;All API requests are handled on the &lt;code&gt;/api/overrides&lt;/code&gt; endpoint. The module supports &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt;, and &lt;code&gt;DELETE&lt;/code&gt;
requests. If you set 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#server&#34;&gt;&lt;code&gt;http_api_prefix&lt;/code&gt;&lt;/a&gt; in your Tempo configuration, prepend it to the path (for example, &lt;code&gt;/tempo/api/overrides&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This endpoint is tenant-specific. If Tempo is run in multitenant mode, all requests should have an appropriate
&lt;code&gt;X-Scope-OrgID&lt;/code&gt; header.&lt;/p&gt;
&lt;p&gt;If the tenant is run in distributed mode, only the query-frontend will accept API requests.&lt;/p&gt;
&lt;h3 id=&#34;operations&#34;&gt;Operations&lt;/h3&gt;
&lt;h4 id=&#34;get-apioverrides&#34;&gt;GET /api/overrides&lt;/h4&gt;
&lt;p&gt;Returns the current overrides and its version.&lt;/p&gt;
&lt;p&gt;Query-parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scope&lt;/code&gt;: whether to return overrides from the API only &lt;code&gt;api&lt;/code&gt; or merge it with the runtime overrides &lt;code&gt;merged&lt;/code&gt;. Defaults
to &lt;code&gt;api&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X GET -v -H &amp;#34;X-Scope-OrgID: 3&amp;#34; http://localhost:3100/api/overrides\?scope=merged&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&#34;post-apioverrides&#34;&gt;POST /api/overrides&lt;/h4&gt;
&lt;p&gt;Update the overrides with the given payload. Note this overwrites any existing overrides.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X POST -v -H &amp;#34;X-Scope-OrgID: 3&amp;#34; -H &amp;#34;If-Match: 1697726795401423&amp;#34; http://localhost:3100/api/overrides --data &amp;#34;{}&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&#34;patch-apioverrides&#34;&gt;PATCH /api/overrides&lt;/h4&gt;
&lt;p&gt;Update the existing overrides by patching it with the payload.
It follows the JSON merge patch protocol (&lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc7386&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;RFC 7386&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X PATCH -v -H &amp;#34;X-Scope-OrgID: 3&amp;#34; http://localhost:3100/api/overrides --data &amp;#34;{\&amp;#34;forwarders\&amp;#34;:null}&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&#34;delete-apioverrides&#34;&gt;DELETE /api/overrides&lt;/h4&gt;
&lt;p&gt;Delete the existing overrides.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X DELETE -H &amp;#34;X-Scope-OrgID: 3&amp;#34; -H &amp;#34;If-Match: 1697726795401423&amp;#34; http://localhost:3100/api/overrides&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;versioning&#34;&gt;Versioning&lt;/h3&gt;
&lt;p&gt;To handle concurrent read and write operations, the backend stores the overrides with a version.
Whenever the overrides are returned, the response has an Etag header with the current version.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;$ curl -v http://localhost:3100/api/overrides
...
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Content-Type: application/json
&amp;lt; Etag: 1697726795401423
&amp;lt; Date: Wed, 07 Feb 2024 17:49:04 GMT
&amp;lt; Content-Length: 118
...&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Requests that modify or delete overrides need to pass the current version using the &lt;code&gt;If-Match&lt;/code&gt; header:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X POST -H &amp;#34;If-Match: 1697726795401423&amp;#34; http://localhost:3100/api/overrides --data &amp;#34;...&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This example uses overrides in the &lt;code&gt;overrides.json&lt;/code&gt; file with the location in &lt;code&gt;pwd&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X POST -H &amp;#34;X-Scope-OrgID: 3&amp;#34; -H &amp;#34;If-Match: 1697726795401423&amp;#34; http://localhost:3100/api/overrides --data @overrides.json&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the version doesn&amp;rsquo;t match the version in the backend, the request is rejected with HTTP error 412.&lt;/p&gt;
&lt;h3 id=&#34;conflicting-runtime-overrides-check&#34;&gt;Conflicting runtime overrides check&lt;/h3&gt;
&lt;p&gt;Overrides set through the user-configurable overrides take priority over runtime overrides.
This can lead to misleading scenarios because a value set in the runtime overrides is not actively being used.&lt;/p&gt;
&lt;p&gt;To warn users about preexisting runtime overrides, there is an optional check for conflicting runtime overrides.
If enabled requests are rejected if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There are no user-configurable overrides yet for this tenant.&lt;/li&gt;
&lt;li&gt;There are runtime overrides set that contain overrides present in the user-configurable overrides.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The check can be enabled in the configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;overrides:
  user_configurable_overrides:
    api:
      check_for_conflicting_runtime_overrides: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can bypass this check by setting the query parameter &lt;code&gt;skip-conflicting-overrides-check=true&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;shell&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-shell&#34;&gt;curl -X POST -H &amp;#34;If-Match: 1697726795401423&amp;#34; http://localhost:3100/api/overrides?skip-conflicting-overrides-check=true --data &amp;#34;...&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="user-configurable-overrides">User-configurable overrides&lt;/h1>
&lt;p>User-configurable overrides in Tempo let you change overrides for your tenant using an API.
Instead of modifying a file or Kubernetes &lt;code>configmap&lt;/code>, you (and other services relying on Tempo) can use this API to
modify the overrides directly.&lt;/p></description></item><item><title>Generic forwarding</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/generic_forwarding/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/generic_forwarding/</guid><content><![CDATA[&lt;h1 id=&#34;generic-forwarding&#34;&gt;Generic forwarding&lt;/h1&gt;
&lt;p&gt;Generic forwarding allows asynchronous replication of ingested traces.
The distributor writes received spans to both Kafka and defined endpoints, if enabled.
This feature works in a best-effort manner, meaning that no retries happen if an error occurs during replication.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;Generic forwarding doesn&amp;rsquo;t work retroactively. After it&amp;rsquo;s enabled, the distributor only replicates freshly ingested spans.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configure-generic-forwarding&#34;&gt;Configure generic forwarding&lt;/h2&gt;
&lt;p&gt;Enabling generic forwarding requires the configuration of the &lt;code&gt;distributor&lt;/code&gt; and &lt;code&gt;overrides&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Define a list of forwarders in the &lt;code&gt;distributor&lt;/code&gt; section. Each forwarder must specify a unique &lt;code&gt;name&lt;/code&gt;, supported &lt;code&gt;backend&lt;/code&gt;, and backend-specific configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reference these forwarders in the &lt;code&gt;overrides&lt;/code&gt; section. This allows for fine-grained control over forwarding and makes it possible to enable this feature globally or on a per-tenant basis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For a detailed view of all the configuration options for the generic forwarding feature,  refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#distributor&#34;&gt;distributor&lt;/a&gt; and 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#overrides&#34;&gt;overrides&lt;/a&gt; configuration pages.&lt;/p&gt;
]]></content><description>&lt;h1 id="generic-forwarding">Generic forwarding&lt;/h1>
&lt;p>Generic forwarding allows asynchronous replication of ingested traces.
The distributor writes received spans to both Kafka and defined endpoints, if enabled.
This feature works in a best-effort manner, meaning that no retries happen if an error occurs during replication.&lt;/p></description></item><item><title>Tune the consistent hash rings</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/consistent_hash_ring/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/consistent_hash_ring/</guid><content><![CDATA[&lt;h1 id=&#34;tune-the-consistent-hash-rings&#34;&gt;Tune the consistent hash rings&lt;/h1&gt;
&lt;p&gt;Tempo uses the &lt;a href=&#34;https://cortexmetrics.io/docs/architecture/#the-hash-ring&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consistent Hash Ring&lt;/a&gt; implementation from Cortex.
By default, the ring is gossiped between all Tempo components.
However, it can be configured to use &lt;a href=&#34;https://www.consul.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consul&lt;/a&gt; or &lt;a href=&#34;https://etcd.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Etcd&lt;/a&gt;, if desired.&lt;/p&gt;
&lt;p&gt;Tempo uses several consistent hash rings.
Each hash ring exists for a distinct reason.&lt;/p&gt;
&lt;h2 id=&#34;distributor&#34;&gt;Distributor&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;Unless you are running with limits, this ring does not impact Tempo operation.&lt;/p&gt;
&lt;p&gt;This ring is only used when &lt;code&gt;global&lt;/code&gt; rate limits are used. The distributors use it to count the other active distributors. Incoming traffic is assumed to be evenly spread across all distributors and &lt;code&gt;(global_rate_limit / # of distributors)&lt;/code&gt; is used to rate limit locally.&lt;/p&gt;
&lt;h2 id=&#34;live-store-partition-ring&#34;&gt;Live-store (partition ring)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Live-stores&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Distributors, Queriers, Block-builders&lt;/p&gt;
&lt;p&gt;The partition ring tracks which Tempo partitions are active and which live-stores own them. Distributors use this ring to determine which partitions to write to when sending data to Kafka. Queriers use it to find the live-stores for querying recent traces. Block-builders use it to determine which partitions to consume from.&lt;/p&gt;
&lt;h2 id=&#34;backend-worker&#34;&gt;Backend-worker&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Backend-workers&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Backend-workers&lt;/p&gt;
&lt;p&gt;The backend-worker ring shards tenant index writing across backend-workers. This ring is only active when the backend-worker is configured with an external KV store for ring membership.&lt;/p&gt;
&lt;h2 id=&#34;metrics-generator-partition-ring&#34;&gt;Metrics-generator (partition ring)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Metrics-generators&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Metrics-generators&lt;/p&gt;
&lt;p&gt;In microservices mode, the metrics-generator partition ring tracks which generator instances own which partitions. This ring is only active when &lt;code&gt;metrics_generator.ring_mode&lt;/code&gt; is set to &lt;code&gt;generator&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;interacting-with-the-rings&#34;&gt;Interacting with the rings&lt;/h2&gt;
&lt;p&gt;Web pages are available at the following endpoints. They show every ring member, their tokens, and include the ability to &amp;ldquo;Forget&amp;rdquo; a ring member. &amp;ldquo;Forgetting&amp;rdquo; is useful when a ring member leaves the ring without properly shutting down, and therefore leaves its tokens in the ring.&lt;/p&gt;
&lt;p&gt;To access a ring page, send a GET request to the Tempo HTTP API. By default, Tempo listens on port &lt;code&gt;3200&lt;/code&gt; (configured with &lt;code&gt;server.http_listen_port&lt;/code&gt;). For example:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;http://&amp;lt;tempo-host&amp;gt;:3200/live-store/ring&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In single-binary mode, any enabled ring endpoints are available on the same host. In microservices mode, each endpoint is available on the component listed in the &lt;strong&gt;Available on&lt;/strong&gt; field.&lt;/p&gt;
&lt;h3 id=&#34;distributor-1&#34;&gt;Distributor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/distributor/ring&lt;/code&gt;&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This endpoint is only available when Tempo is configured with 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#ingestion-rate-strategy&#34;&gt;the global ingestion rate strategy&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Unhealthy distributors have little impact but should be forgotten to reduce the cost of maintaining the ring.&lt;/p&gt;
&lt;h3 id=&#34;live-store-partition-ring-1&#34;&gt;Live-store (partition ring)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors, Queriers, Live-stores&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/partition-ring&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The partition ring shows partition ownership across live-stores. Unhealthy live-stores may cause recent data queries to degrade.&lt;/p&gt;
&lt;h3 id=&#34;live-store&#34;&gt;Live-store&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors, Queriers, Live-stores&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/live-store/ring&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;backend-worker-1&#34;&gt;Backend-worker&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Backend-workers&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/backend-worker/ring&lt;/code&gt;&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This endpoint is only available when &lt;code&gt;backend_worker.ring.kvstore.store&lt;/code&gt; is set to a non-empty value other than &lt;code&gt;inmemory&lt;/code&gt; (for example, &lt;code&gt;memberlist&lt;/code&gt;, &lt;code&gt;consul&lt;/code&gt;, or &lt;code&gt;etcd&lt;/code&gt;).&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The backend-worker ring page shows how tenant index writing is distributed across workers. Forget unhealthy workers so that sharding redistributes correctly.&lt;/p&gt;
&lt;h3 id=&#34;metrics-generator-partition-ring-1&#34;&gt;Metrics-generator (partition ring)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Metrics-generators&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/partition/ring&lt;/code&gt;&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This endpoint is only available in microservices mode when &lt;code&gt;metrics_generator.ring_mode&lt;/code&gt; is set to &lt;code&gt;generator&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The metrics-generator partition ring shows partition ownership across generator instances.&lt;/p&gt;
&lt;h2 id=&#34;configuring-the-rings&#34;&gt;Configuring the rings&lt;/h2&gt;
&lt;p&gt;Ring/Lifecycler configuration control how a component interacts with the ring. Refer to the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/&#34;&gt;configuration&lt;/a&gt; topic for more details.&lt;/p&gt;
]]></content><description>&lt;h1 id="tune-the-consistent-hash-rings">Tune the consistent hash rings&lt;/h1>
&lt;p>Tempo uses the &lt;a href="https://cortexmetrics.io/docs/architecture/#the-hash-ring" target="_blank" rel="noopener noreferrer">Consistent Hash Ring&lt;/a> implementation from Cortex.
By default, the ring is gossiped between all Tempo components.
However, it can be configured to use &lt;a href="https://www.consul.io/" target="_blank" rel="noopener noreferrer">Consul&lt;/a> or &lt;a href="https://etcd.io/" target="_blank" rel="noopener noreferrer">Etcd&lt;/a>, if desired.&lt;/p></description></item><item><title>Zone-aware replication for live-stores</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/zone-aware-live-stores/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/zone-aware-live-stores/</guid><content><![CDATA[&lt;h1 id=&#34;zone-aware-replication-for-live-stores&#34;&gt;Zone-aware replication for live-stores&lt;/h1&gt;
&lt;p&gt;Zone awareness is a feature that ensures data is replicated across failure domains (which we refer to as &amp;ldquo;zones&amp;rdquo;) to provide greater reliability.
A failure domain is whatever you define it to be, but commonly may be an availability zone, data center, or server rack.&lt;/p&gt;
&lt;p&gt;When zone awareness is set up for live-stores, each Tempo partition is owned by one live-store per zone.
This means that if a live-store in one zone becomes unavailable, the live-store in the other zone can continue serving queries for that partition.
While data is replicated across zones (RF2), the read quorum is 1. The queriers only need a response from one live-store per partition.
This provides high availability without requiring data deduplication on the read path.&lt;/p&gt;
]]></content><description>&lt;h1 id="zone-aware-replication-for-live-stores">Zone-aware replication for live-stores&lt;/h1>
&lt;p>Zone awareness is a feature that ensures data is replicated across failure domains (which we refer to as &amp;ldquo;zones&amp;rdquo;) to provide greater reliability.
A failure domain is whatever you define it to be, but commonly may be an availability zone, data center, or server rack.&lt;/p></description></item></channel></rss>