<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Grafana Mimir components on Grafana Labs</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/</link><description>Recent content in Grafana Mimir components on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/mimir/v2.12.x/references/architecture/components/index.xml" rel="self" type="application/rss+xml"/><item><title>Grafana Mimir compactor</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/compactor/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/compactor/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-compactor&#34;&gt;Grafana Mimir compactor&lt;/h1&gt;
&lt;p&gt;The compactor increases query performance and reduces long-term storage usage by combining blocks.&lt;/p&gt;
&lt;p&gt;The compactor is the component responsible for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compacting multiple blocks of a given tenant into a single, optimized larger block. This deduplicates chunks and reduces the size of the index, resulting in reduced storage costs. Querying fewer blocks is faster, so it also increases query speed.&lt;/li&gt;
&lt;li&gt;Keeping the per-tenant bucket index updated. The &lt;a href=&#34;../../bucket-index/&#34;&gt;bucket index&lt;/a&gt; is used by &lt;a href=&#34;../querier/&#34;&gt;queriers&lt;/a&gt;, &lt;a href=&#34;../store-gateway/&#34;&gt;store-gateways&lt;/a&gt;, and &lt;a href=&#34;../ruler/&#34;&gt;rulers&lt;/a&gt; to discover both new blocks and deleted blocks in the storage.&lt;/li&gt;
&lt;li&gt;Deleting blocks that are no longer within a configurable retention period.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The compactor is stateless.&lt;/p&gt;
&lt;h2 id=&#34;how-compaction-works&#34;&gt;How compaction works&lt;/h2&gt;
&lt;p&gt;Compaction occurs on a per-tenant basis.&lt;/p&gt;
&lt;p&gt;The compactor runs at regular, configurable intervals.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vertical compaction&lt;/strong&gt; merges all the blocks of a tenant uploaded by ingesters for the same time range (2 hours ranges by default) into a single block. It also deduplicates samples that were originally written to N blocks as a result of replication. Vertical compaction reduces the number of blocks for a single time range from the quantity of ingesters down to one block per tenant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Horizontal compaction&lt;/strong&gt; triggers after a vertical compaction. It compacts several blocks with adjacent range periods into a single larger block. The total size of the associated block chunks does not change after horizontal compaction. The horizontal compaction may significantly reduce the size of the index and the index-header kept in memory by store-gateways.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;compactor-horizontal-and-vertical-compaction.png&#34;
  alt=&#34;Compactor - horizontal and vertical compaction&#34;/&gt;&lt;/p&gt;
&lt;!-- Diagram source at https://docs.google.com/presentation/d/1bHp8_zcoWCYoNU2AhO2lSagQyuIrghkCncViSqn14cU/edit --&gt;
&lt;h2 id=&#34;scaling&#34;&gt;Scaling&lt;/h2&gt;
&lt;p&gt;Compaction can be tuned for clusters with large tenants. Configuration specifies both vertical and horizontal scaling of how the compactor runs as it compacts on a per-tenant basis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vertical scaling&lt;/strong&gt;&lt;br /&gt;
The setting &lt;code&gt;-compactor.compaction-concurrency&lt;/code&gt; configures the max number of concurrent compactions running in a single compactor instance. Each compaction uses one CPU core.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt;&lt;br /&gt;
By default, tenant blocks can be compacted by any Grafana Mimir compactor. When you enable compactor &lt;a href=&#34;../../../../configure/configure-shuffle-sharding/&#34;&gt;shuffle sharding&lt;/a&gt; by setting &lt;code&gt;-compactor.compactor-tenant-shard-size&lt;/code&gt; (or its respective YAML configuration option) to a value higher than &lt;code&gt;0&lt;/code&gt; and lower than the number of available compactors, only the specified number of compactors are eligible to compact blocks for a given tenant.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;compaction-algorithm&#34;&gt;Compaction algorithm&lt;/h2&gt;
&lt;p&gt;Mimir uses a sophisticated compaction algorithm called split-and-merge.&lt;/p&gt;
&lt;p&gt;By design, the split-and-merge algorithm overcomes time series database (TSDB) index limitations, and it avoids situations in which compacted blocks grow indefinitely for a very large tenant at any compaction stage.&lt;/p&gt;
&lt;p&gt;This compaction strategy is a two-stage process: split and merge.
The default configuration disables the split stage.&lt;/p&gt;
&lt;p&gt;To split, the first level of compaction, for example &lt;code&gt;2h&lt;/code&gt;, the compactor divides all source blocks into &lt;em&gt;N&lt;/em&gt; (&lt;code&gt;-compactor.split-groups&lt;/code&gt;) groups. For each group, the compactor compacts the blocks, but instead of producing a single result block, it outputs &lt;em&gt;M&lt;/em&gt; (&lt;code&gt;-compactor.split-and-merge-shards&lt;/code&gt;) blocks, known as &lt;em&gt;split blocks&lt;/em&gt;. Each split block contains only a subset of the series belonging to a given shard out of &lt;em&gt;M&lt;/em&gt; shards. At the end of the split stage, the compactor produces &lt;em&gt;N * M&lt;/em&gt; blocks with a reference to their respective shard in the block’s &lt;code&gt;meta.json&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The compactor merges the split blocks for each shard. This compacts all &lt;em&gt;N&lt;/em&gt; split blocks of a given shard. The merge reduces the number of blocks from &lt;em&gt;N * M&lt;/em&gt; to &lt;em&gt;M&lt;/em&gt;. For a given compaction time range, there will be a compacted block for each of the &lt;em&gt;M&lt;/em&gt; shards.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;compactor-split-and-merge.png&#34;
  alt=&#34;Compactor - split-and-merge compaction strategy&#34;/&gt;&lt;/p&gt;
&lt;!-- Diagram source at https://docs.google.com/presentation/d/1bHp8_zcoWCYoNU2AhO2lSagQyuIrghkCncViSqn14cU/edit --&gt;
&lt;p&gt;The merge then runs on other configured compaction time ranges, for example 12h and 24h. It compacts blocks belonging to the same shard.&lt;/p&gt;
&lt;p&gt;This strategy is suitable for clusters with large tenants. The number of shards &lt;em&gt;M&lt;/em&gt; is configurable on a per-tenant basis using &lt;code&gt;-compactor.split-and-merge-shards&lt;/code&gt;, and it can be adjusted based on the number of series of each tenant. The more a tenant grows in terms of series, the more you can grow the configured number of shards. Doing so improves compaction parallelization and keeps each per-shard compacted block size under control. We recommend 1 shard per every 8 million active series in a tenant. For example, for a tenant with 100 million active series, use approximately 12 shards. Use an even number for the count.&lt;/p&gt;
&lt;p&gt;The number of split groups, &lt;em&gt;N&lt;/em&gt;, can also be adjusted per tenant using the &lt;code&gt;-compactor.split-groups&lt;/code&gt; option. Increasing this value produces more compaction jobs with fewer blocks during the split stage. This allows multiple compactors to work on these jobs, and finish the splitting stage faster. However, increasing this value also generates more intermediate blocks during the split stage, which will only be reduced later in the merge stage.&lt;/p&gt;
&lt;p&gt;If the configuration of &lt;code&gt;-compactor.split-and-merge-shards&lt;/code&gt; changes during compaction, the change will affect only the compaction of blocks which have not yet been split. Already split blocks will use the original configuration when merged. The original configuration is stored in the &lt;code&gt;meta.json&lt;/code&gt; of each split block.&lt;/p&gt;
&lt;p&gt;Splitting and merging can be horizontally scaled. Non-conflicting and non-overlapping jobs will be executed in parallel.&lt;/p&gt;
&lt;h2 id=&#34;compactor-sharding&#34;&gt;Compactor sharding&lt;/h2&gt;
&lt;p&gt;The compactor shards compaction jobs, either from a single tenant or multiple tenants. The compaction of a single tenant can be split and processed by multiple compactor instances.&lt;/p&gt;
&lt;p&gt;Whenever the pool of compactors grows or shrinks, tenants and jobs are resharded across the available compactor instances without any manual intervention.&lt;/p&gt;
&lt;p&gt;Compactor sharding uses a &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt;. At startup, a compactor generates random tokens and registers itself to the compactor hash ring. While running, it periodically scans the storage bucket at every interval defined by &lt;code&gt;-compactor.compaction-interval&lt;/code&gt;, to discover the list of tenants in storage and to compact blocks for each tenant whose hash matches the token ranges assigned to the instance itself within the hash ring.&lt;/p&gt;
&lt;p&gt;To configure the compactors&amp;rsquo; hash ring, refer to &lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;waiting-for-a-stable-hash-ring-at-startup&#34;&gt;Waiting for a stable hash ring at startup&lt;/h3&gt;
&lt;p&gt;A cluster cold start or an increase of two or more compactor instances at the same time may result in each new compactor instance starting at a slightly different time. Then, each compactor runs its first compaction based on a different state of the hash ring. This is not an error condition, but it may be inefficient, because multiple compactor instances may start compacting the same tenant at nearly the same time.&lt;/p&gt;
&lt;p&gt;To mitigate the issue, compactors can be configured to wait for a stable hash ring at startup. A ring is considered stable if no instance is added to or removed from the hash ring for at least &lt;code&gt;-compactor.ring.wait-stability-min-duration&lt;/code&gt;. The maximum time the compactor will wait is controlled by the flag &lt;code&gt;-compactor.ring.wait-stability-max-duration&lt;/code&gt; (or the respective YAML configuration option). Once the compactor has finished waiting, either because the ring stabilized or because the maximum wait time was reached, it will start up normally.&lt;/p&gt;
&lt;p&gt;The default value of zero for &lt;code&gt;-compactor.ring.wait-stability-min-duration&lt;/code&gt; disables waiting for ring stability.&lt;/p&gt;
&lt;h2 id=&#34;compaction-jobs-order&#34;&gt;Compaction jobs order&lt;/h2&gt;
&lt;p&gt;The compactor allows configuring of the compaction jobs order via the &lt;code&gt;-compactor.compaction-jobs-order&lt;/code&gt; flag (or its respective YAML config option). The configured ordering defines which compaction jobs should be executed first. The following values of &lt;code&gt;-compactor.compaction-jobs-order&lt;/code&gt; are supported:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;smallest-range-oldest-blocks-first&lt;/code&gt; (default)&lt;/p&gt;
&lt;p&gt;This ordering gives priority to smallest range, oldest blocks first.&lt;/p&gt;
&lt;p&gt;For example, with compaction ranges &lt;code&gt;2h, 12h, 24h&lt;/code&gt;, the compactor will compact the 2h ranges first, and among them give priority to the oldest blocks. Once all blocks in the 2h range have been compacted, it moves to the 12h range, and finally to 24h one.&lt;/p&gt;
&lt;p&gt;All split jobs are moved to the front of the work queue, because finishing all split jobs in a given time range unblocks the merge jobs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;newest-blocks-first&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This ordering gives priority to the most recent time ranges first, regardless of their compaction level.&lt;/p&gt;
&lt;p&gt;For example, with compaction ranges &lt;code&gt;2h, 12h, 24h&lt;/code&gt;, the compactor compacts the most recent blocks first (up to the 24h range), and then moves to older blocks. This policy favours the most recent blocks, assuming they are queried the most frequently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;blocks-deletion&#34;&gt;Blocks deletion&lt;/h2&gt;
&lt;p&gt;Following a successful compaction, the original blocks are deleted from the storage. Block deletion is not immediate; it follows a two step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An original block is marked for deletion; this is a soft delete&lt;/li&gt;
&lt;li&gt;Once a block has been marked for deletion for longer than the configurable &lt;code&gt;-compactor.deletion-delay&lt;/code&gt;, the block is deleted from storage; this is a hard delete&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The compactor is responsible for both marking blocks and for hard deletion.
Soft deletion is based on a small &lt;code&gt;deletion-mark.json&lt;/code&gt; file stored within the block location in the bucket.&lt;/p&gt;
&lt;p&gt;The soft delete mechanism gives queriers, rulers, and store-gateways time to discover the new compacted blocks before the original blocks are deleted. If those original blocks were immediately hard deleted, some queries involving the compacted blocks could temporarily fail or return partial results.&lt;/p&gt;
&lt;h2 id=&#34;blocks-retention&#34;&gt;Blocks retention&lt;/h2&gt;
&lt;p&gt;The compactor is responsible for enforcing the storage retention, deleting the blocks that contain samples that are older than the configured retention period from the long-term storage.
The storage retention is disabled by default, and no data will be deleted from the long-term storage unless you explicitly configure the retention period.&lt;/p&gt;
&lt;p&gt;For more information, refer to &lt;a href=&#34;../../../../configure/configure-metrics-storage-retention/&#34;&gt;Configure metrics storage retention&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;compactor-disk-utilization&#34;&gt;Compactor disk utilization&lt;/h2&gt;
&lt;p&gt;The compactor needs to download blocks from the bucket to the local disk, and the compactor needs to store compacted blocks to the local disk before uploading them to the bucket. The largest tenants may need a lot of disk space.&lt;/p&gt;
&lt;p&gt;Assuming &lt;code&gt;max_compaction_range_blocks_size&lt;/code&gt; is the total block size for the largest tenant during the longest &lt;code&gt;-compactor.block-ranges&lt;/code&gt; period, the expression that estimates the minimum disk space required is:&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;compactor.compaction-concurrency * max_compaction_range_blocks_size * 2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, assuming the largest &lt;code&gt;-compactor.block-ranges&lt;/code&gt; is &lt;code&gt;24h&lt;/code&gt; (the default), you could estimate needing 150GB of disk space for every 10M active series owned by the largest tenant. For example, if your largest tenant has 30M active series and &lt;code&gt;-compactor.compaction-concurrency=1&lt;/code&gt;, we would recommend having a disk with at least 450GB available.&lt;/p&gt;
&lt;h2 id=&#34;compactor-configuration&#34;&gt;Compactor configuration&lt;/h2&gt;
&lt;p&gt;Refer to the &lt;a href=&#34;../../../../configure/configuration-parameters/#compactor&#34;&gt;compactor&lt;/a&gt;
block section and the &lt;a href=&#34;../../../../configure/configuration-parameters/#limits&#34;&gt;limits&lt;/a&gt; block section for details of compaction-related configuration.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;../alertmanager/&#34;&gt;alertmanager&lt;/a&gt; and &lt;a href=&#34;../ruler/&#34;&gt;ruler&lt;/a&gt; components can also use object storage to store their configurations and rules uploaded by users. In that case a separate bucket should be created to store alertmanager configurations and rules: using the same bucket between ruler/alertmanager and blocks will cause issues with the compactor.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-compactor">Grafana Mimir compactor&lt;/h1>
&lt;p>The compactor increases query performance and reduces long-term storage usage by combining blocks.&lt;/p>
&lt;p>The compactor is the component responsible for:&lt;/p>
&lt;ul>
&lt;li>Compacting multiple blocks of a given tenant into a single, optimized larger block. This deduplicates chunks and reduces the size of the index, resulting in reduced storage costs. Querying fewer blocks is faster, so it also increases query speed.&lt;/li>
&lt;li>Keeping the per-tenant bucket index updated. The &lt;a href="../../bucket-index/">bucket index&lt;/a> is used by &lt;a href="../querier/">queriers&lt;/a>, &lt;a href="../store-gateway/">store-gateways&lt;/a>, and &lt;a href="../ruler/">rulers&lt;/a> to discover both new blocks and deleted blocks in the storage.&lt;/li>
&lt;li>Deleting blocks that are no longer within a configurable retention period.&lt;/li>
&lt;/ul>
&lt;p>The compactor is stateless.&lt;/p></description></item><item><title>Grafana Mimir distributor</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/distributor/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/distributor/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-distributor&#34;&gt;Grafana Mimir distributor&lt;/h1&gt;
&lt;p&gt;The distributor is a stateless component that receives time-series data from Prometheus or the Grafana agent.
The distributor validates the data for correctness and ensures that it is within the configured limits for a given tenant.
The distributor then divides the data into batches and sends it to multiple &lt;a href=&#34;../ingester/&#34;&gt;ingesters&lt;/a&gt; in parallel, shards the series among ingesters, and replicates each series by the configured replication factor. By default, the configured replication factor is three.&lt;/p&gt;
&lt;h2 id=&#34;validation&#34;&gt;Validation&lt;/h2&gt;
&lt;p&gt;The distributor cleans and validates data that it receives before writing the data to the ingesters.
Because a single request can contain valid and invalid metrics, samples, metadata, and exemplars, the distributor only passes valid data to the ingesters. The distributor does not include invalid data in its requests to the ingesters.
If the request contains invalid data, the distributor returns a 400 HTTP status code and the details appear in the response body.
The details about the first invalid data are typically logged by the sender, be it Prometheus or Grafana Agent.&lt;/p&gt;
&lt;p&gt;The distributor data cleanup includes the following transformation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The metric metadata &lt;code&gt;help&lt;/code&gt; is truncated to fit in the length defined via the &lt;code&gt;-validation.max-metadata-length&lt;/code&gt; flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The distributor validation includes the following checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The metric metadata and labels conform to the &lt;a href=&#34;https://prometheus.io/docs/concepts/data_model/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus exposition format&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The metric metadata (&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;unit&lt;/code&gt;) are not longer than what is defined via the &lt;code&gt;-validation.max-metadata-length&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;The number of labels of each metric is not higher than &lt;code&gt;-validation.max-label-names-per-series&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each metric label name is not longer than &lt;code&gt;-validation.max-length-label-name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each metric label value is not longer than &lt;code&gt;-validation.max-length-label-value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each sample timestamp is not newer than &lt;code&gt;-validation.create-grace-period&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each exemplar has a timestamp and at least one non-empty label name and value pair.&lt;/li&gt;
&lt;li&gt;Each exemplar has no more than 128 labels.&lt;/li&gt;
&lt;/ul&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;For each tenant, you can override the validation checks by modifying the overrides section of the &lt;a href=&#34;../../../../configure/about-runtime-configuration/&#34;&gt;runtime configuration&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;rate-limiting&#34;&gt;Rate limiting&lt;/h2&gt;
&lt;p&gt;The distributor includes two different types of rate limiters that apply to each tenant.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Request rate&lt;/strong&gt;&lt;br /&gt;
The maximum number of requests per second that can be served across Grafana Mimir cluster for each tenant.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ingestion rate&lt;/strong&gt;&lt;br /&gt;
The maximum samples per second that can be ingested across Grafana Mimir cluster for each tenant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If any of these rates is exceeded, the distributor drops the request and returns an HTTP 429 response code.&lt;/p&gt;
&lt;p&gt;Internally, these limits are implemented using a per-distributor local rate limiter.
The local rate limiter for each distributor is configured with a limit of &lt;code&gt;limit / N&lt;/code&gt;, where &lt;code&gt;N&lt;/code&gt; is the number of healthy distributor replicas.
The distributor automatically adjusts the request and ingestion rate limits if the number of distributor replicas change.
Because these rate limits are implemented using a per-distributor local rate limiter, they require that write requests are &lt;a href=&#34;#load-balancing-across-distributors&#34;&gt;evenly distributed across the pool of distributors&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Use the following flags to configure the rate limits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-distributor.request-rate-limit&lt;/code&gt;: Request rate limit, which is per tenant, and which is in requests per second&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-distributor.request-burst-size&lt;/code&gt;: Request burst size (in number of requests) allowed, which is per tenant&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-distributor.ingestion-rate-limit&lt;/code&gt;: Ingestion rate limit, which is per tenant, and which is in samples per second&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-distributor.ingestion-burst-size&lt;/code&gt;: Ingestion burst size (in number of samples) allowed, which is per tenant&lt;/li&gt;
&lt;/ul&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;You can override rate limiting on a per-tenant basis by setting &lt;code&gt;request_rate&lt;/code&gt;, &lt;code&gt;ingestion_rate&lt;/code&gt;, &lt;code&gt;request_burst_size&lt;/code&gt; and &lt;code&gt;ingestion_burst_size&lt;/code&gt; in the overrides section of the runtime configuration.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&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;By default, Prometheus remote write doesn&amp;rsquo;t retry requests on 429 HTTP response status code. To modify this behavior, use &lt;code&gt;retry_on_http_429: true&lt;/code&gt; in the Prometheus &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;remote_write&lt;/code&gt; configuration&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;configuration&#34;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;The distributors form a &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; (called the distributors’ ring) to discover each other and enforce limits correctly.
To configure the distributors&amp;rsquo; hash ring, refer to &lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;high-availability-tracker&#34;&gt;High-availability tracker&lt;/h2&gt;
&lt;p&gt;Remote write senders, such as Prometheus, can be configured in pairs, which means that metrics continue to be scraped and written to Grafana Mimir even when one of the remote write senders is down for maintenance or is unavailable due to a failure.
We refer to this configuration as high-availability (HA) pairs.&lt;/p&gt;
&lt;p&gt;The distributor includes an HA tracker.
When the HA tracker is enabled, the distributor deduplicates incoming series from Prometheus HA pairs.
This enables you to have multiple HA replicas of the same Prometheus servers that write the same series to Mimir and then deduplicates the series in the Mimir distributor.&lt;/p&gt;
&lt;p&gt;For more information about HA deduplication and how to configure it, refer to &lt;a href=&#34;../../../../configure/configure-high-availability-deduplication/&#34;&gt;configure HA deduplication&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;sharding-and-replication&#34;&gt;Sharding and replication&lt;/h2&gt;
&lt;p&gt;The distributor shards and replicates incoming series across ingesters.
You can configure the number of ingester replicas that each series is written to via the &lt;code&gt;-ingester.ring.replication-factor&lt;/code&gt; flag, which is &lt;code&gt;3&lt;/code&gt; by default.
Distributors use consistent hashing, in conjunction with a configurable replication factor, to determine which ingesters receive a given series.&lt;/p&gt;
&lt;p&gt;Sharding and replication uses the ingesters&amp;rsquo; hash ring.
For each incoming series, the distributor computes a hash using the metric name, labels, and tenant ID.
The computed hash is called a &lt;em&gt;token&lt;/em&gt;.
The distributor looks up the token in the hash ring to determine which ingesters to write a series to.&lt;/p&gt;
&lt;p&gt;For more information, see &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;quorum-consistency&#34;&gt;Quorum consistency&lt;/h4&gt;
&lt;p&gt;Because distributors share access to the same hash ring, write requests can be sent to any distributor. You can also set up a stateless load balancer in front of it.&lt;/p&gt;
&lt;p&gt;To ensure consistent query results, Mimir uses &lt;a href=&#34;https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Dynamo-style&lt;/a&gt; quorum consistency on reads and writes.
The distributor waits for a successful response from &lt;code&gt;n&lt;/code&gt;/2 &#43; 1 ingesters, where &lt;code&gt;n&lt;/code&gt; is the configured replication factor, before sending a successful response to the Prometheus write request.&lt;/p&gt;
&lt;h2 id=&#34;load-balancing-across-distributors&#34;&gt;Load balancing across distributors&lt;/h2&gt;
&lt;p&gt;We recommend randomly load balancing write requests across distributor instances.
If you&amp;rsquo;re running Grafana Mimir in a Kubernetes cluster, you can define a Kubernetes &lt;a href=&#34;https://kubernetes.io/docs/concepts/services-networking/service/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Service&lt;/a&gt; as ingress for the distributors.&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;A Kubernetes Service balances TCP connections across Kubernetes endpoints and doesn&amp;rsquo;t balance HTTP requests within a single TCP connection.&lt;/p&gt;
&lt;p&gt;If you enable HTTP persistent connections, also known as HTTP keep-alive, Prometheus reuses the same TCP connection for each remote-write HTTP request of a remote-write shard.
This can cause distributors to receive an uneven distribution of remote-write HTTP requests.&lt;/p&gt;
&lt;p&gt;To improve the balancing of requests between distributors, consider increasing &lt;code&gt;min_shards&lt;/code&gt; in the Prometheus &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;remote write&lt;/code&gt; configuration&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;configuration-1&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The distributors must form a hash ring (also called the &lt;em&gt;distributors ring&lt;/em&gt;) so that they can discover each other and correctly enforce limits.&lt;/p&gt;
&lt;p&gt;The default configuration uses &lt;code&gt;memberlist&lt;/code&gt; as backend for the distributors ring.
If you want to configure a different backend, for example, &lt;code&gt;consul&lt;/code&gt; or &lt;code&gt;etcd&lt;/code&gt;, you can use the following CLI flags (and their respective YAML configuration options) to configure the distributors ring KV store:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-distributor.ring.store&lt;/code&gt;: The backend storage to use.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-distributor.ring.consul.*&lt;/code&gt;: The Consul client configuration. Set this flag only if &lt;code&gt;consul&lt;/code&gt; is the configured backend storage.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-distributor.ring.etcd.*&lt;/code&gt;: The etcd client configuration. Set this flag only if &lt;code&gt;etcd&lt;/code&gt; is the configured backend storage.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="grafana-mimir-distributor">Grafana Mimir distributor&lt;/h1>
&lt;p>The distributor is a stateless component that receives time-series data from Prometheus or the Grafana agent.
The distributor validates the data for correctness and ensures that it is within the configured limits for a given tenant.
The distributor then divides the data into batches and sends it to multiple &lt;a href="../ingester/">ingesters&lt;/a> in parallel, shards the series among ingesters, and replicates each series by the configured replication factor. By default, the configured replication factor is three.&lt;/p></description></item><item><title>Grafana Mimir ingester</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/ingester/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/ingester/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-ingester&#34;&gt;Grafana Mimir ingester&lt;/h1&gt;
&lt;p&gt;The ingester is a stateful component that writes incoming series to &lt;a href=&#34;../../../../get-started/about-grafana-mimir-architecture/#long-term-storage&#34;&gt;long-term storage&lt;/a&gt; on the write path and returns series samples for queries on the read path.&lt;/p&gt;
&lt;p&gt;Incoming time series data from &lt;a href=&#34;../distributor/&#34;&gt;distributors&lt;/a&gt; are temporarily stored in the ingester&amp;rsquo;s memory or offloaded to disk before being written to long-term storage.
Eventually, all series are written to disk and periodically uploaded (by default every two hours) to the long-term storage.
For this reason, the &lt;a href=&#34;../querier/&#34;&gt;queriers&lt;/a&gt; might need to fetch samples from both ingesters and long-term storage while executing a query on the read path.&lt;/p&gt;
&lt;p&gt;Any Grafana Mimir component that calls the ingesters starts by first looking up ingesters registered in the &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; to determine which ingesters are available.
Each ingester could be in one of the following states:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PENDING&lt;/code&gt;&lt;br /&gt;
The ingester has just started. While in this state, the ingester does not receive write or read requests.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JOINING&lt;/code&gt;&lt;br /&gt;
The ingester starts up and joins the ring. While in this state, the ingester does not receive write or read requests.
The ingester loads tokens from disk (if &lt;code&gt;-ingester.ring.tokens-file-path&lt;/code&gt; is configured) or generates a set of new random tokens.
Finally, the ingester optionally observes the ring for token conflicts, and once resolved, moves to the &lt;code&gt;ACTIVE&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ACTIVE&lt;/code&gt;&lt;br /&gt;
The ingester is up and running. While in this state, the ingester can receive both write and read requests.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LEAVING&lt;/code&gt;&lt;br /&gt;
The ingester is shutting down and leaving the ring. While in this state, the ingester doesn&amp;rsquo;t receive write requests, but can still receive read requests.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UNHEALTHY&lt;/code&gt;&lt;br /&gt;
The ingester has failed to heartbeat to the hash ring. While in this state, distributors bypass the ingester, which means that the ingester does not receive write or read requests.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To configure the ingesters&amp;rsquo; hash ring, refer to &lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ingesters-write-de-amplification&#34;&gt;Ingesters write de-amplification&lt;/h2&gt;
&lt;p&gt;Ingesters store recently received samples in-memory in order to perform write de-amplification.
If the ingesters immediately write received samples to the long-term storage, the system would have difficulty scaling due to the high pressure on the long-term storage.
For this reason, the ingesters batch and compress samples in-memory and periodically upload them to the long-term storage.&lt;/p&gt;
&lt;p&gt;Write de-amplification is a key factor in reducing Mimir&amp;rsquo;s total cost of ownership (TCO).&lt;/p&gt;
&lt;h2 id=&#34;ingesters-failure-and-data-loss&#34;&gt;Ingesters failure and data loss&lt;/h2&gt;
&lt;p&gt;If an ingester process crashes or exits abruptly, any in-memory time series data that have not yet been uploaded to long-term storage might be lost.
There are the following ways to mitigate this failure mode:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Replication&lt;/li&gt;
&lt;li&gt;Write-ahead log (WAL)&lt;/li&gt;
&lt;li&gt;Write-behind log (WBL), only used if out-of-order ingestion is enabled.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;replication-and-availability&#34;&gt;Replication and availability&lt;/h3&gt;
&lt;p&gt;Writes to the Mimir cluster are successful if a majority of ingesters received the data. With the default replication factor of 3, this means 2 out of 3 writes to ingesters must succeed.
If the Mimir cluster loses a minority of ingesters, the in-memory series samples held by the lost ingesters are available in at least one other ingester, meaning no time series samples are lost.
If a majority of ingesters fail, time series might be lost if the failure affects all the ingesters holding the replicas of a specific time series.&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;Replication only happens at write time. If an ingester is unavailable during a period when writes are actively being written to other ingesters, that particular ingester will never recover those missed samples.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;write-ahead-log&#34;&gt;Write-ahead log&lt;/h3&gt;
&lt;p&gt;The write-ahead log (WAL) writes all incoming series to a persistent disk until the series are uploaded to the long-term storage.
If an ingester fails, a subsequent process restart replays the WAL and recovers the in-memory series samples.&lt;/p&gt;
&lt;p&gt;Unlike sole replication, the WAL ensures that in-memory time series data are not lost in the case of multiple ingester failures. Each ingester can recover the data from the WAL after a subsequent restart.&lt;/p&gt;
&lt;p&gt;Replication is still recommended in order to gracefully handle a single ingester failure.&lt;/p&gt;
&lt;h3 id=&#34;write-behind-log&#34;&gt;Write-behind log&lt;/h3&gt;
&lt;p&gt;The write-behind log (WBL) is similar to the WAL, but it only writes incoming out-of-order samples to a persistent disk until the series are uploaded to long-term storage.&lt;/p&gt;
&lt;p&gt;There is a different log for this because it is not possible to know if a sample is out-of-order until Mimir tries to append it.
First Mimir needs to attempt to append it, the TSDB will detect that it is out-of-order, append it anyway if out-of-order is enabled and then write it to the log.&lt;/p&gt;
&lt;p&gt;If the ingesters fail, the same characteristics as in the WAL apply.&lt;/p&gt;
&lt;h2 id=&#34;zone-aware-replication&#34;&gt;Zone aware replication&lt;/h2&gt;
&lt;p&gt;Zone aware replication ensures that the ingester replicas for a given time series are divided across different zones.
Zones can represent logical or physical failure domains, for example, different data centers.
Dividing replicas across multiple zones prevents data loss and service interruptions when there is a zone-wide outage.&lt;/p&gt;
&lt;p&gt;To set up multi-zone replication, refer to &lt;a href=&#34;../../../../configure/configure-zone-aware-replication/&#34;&gt;Configuring zone-aware replication&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;shuffle-sharding&#34;&gt;Shuffle sharding&lt;/h2&gt;
&lt;p&gt;Shuffle sharding can be used to reduce the effect that multiple tenants can have on each other.&lt;/p&gt;
&lt;p&gt;For more information on shuffle sharding, refer to &lt;a href=&#34;../../../../configure/configure-shuffle-sharding/&#34;&gt;Configuring shuffle sharding&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;out-of-order-samples-ingestion&#34;&gt;Out-of-order samples ingestion&lt;/h2&gt;
&lt;p&gt;Out-of-order samples are discarded by default. If the system writing samples to Mimir produces out-of-order samples, you can enable ingestion of such samples.&lt;/p&gt;
&lt;p&gt;For more information about out-of-order samples ingestion, refer to &lt;a href=&#34;../../../../configure/configure-out-of-order-samples-ingestion/&#34;&gt;Configuring out of order samples ingestion&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-ingester">Grafana Mimir ingester&lt;/h1>
&lt;p>The ingester is a stateful component that writes incoming series to &lt;a href="../../../../get-started/about-grafana-mimir-architecture/#long-term-storage">long-term storage&lt;/a> on the write path and returns series samples for queries on the read path.&lt;/p></description></item><item><title>Grafana Mimir querier</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/querier/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/querier/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-querier&#34;&gt;Grafana Mimir querier&lt;/h1&gt;
&lt;p&gt;The querier is a stateless component that evaluates &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/basics/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;PromQL&lt;/a&gt;
expressions by fetching time series and labels on the read path.&lt;/p&gt;
&lt;p&gt;The querier uses the &lt;a href=&#34;../store-gateway/&#34;&gt;store-gateway&lt;/a&gt; component to query the &lt;a href=&#34;../../../../get-started/about-grafana-mimir-architecture/#long-term-storage&#34;&gt;long-term storage&lt;/a&gt; and the &lt;a href=&#34;../ingester/&#34;&gt;ingester&lt;/a&gt; component to query recently written data.&lt;/p&gt;
&lt;h2 id=&#34;how-it-works&#34;&gt;How it works&lt;/h2&gt;
&lt;p&gt;To find the correct blocks to look up at query time, queriers lazily download the bucket index when they receive the first query for a given tenant. The querier caches the bucket index in memory and periodically keeps it up-to-date.&lt;/p&gt;
&lt;p&gt;The bucket index contains a list of blocks and block deletion marks of a tenant. The querier later uses the list of blocks and block deletion marks to locate the set of blocks that need to be queried for the given query.&lt;/p&gt;
&lt;h3 id=&#34;anatomy-of-a-query-request&#34;&gt;Anatomy of a query request&lt;/h3&gt;
&lt;p&gt;When a querier receives a query range request, the request contains the following parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;query&lt;/code&gt;: the PromQL query expression (for example, &lt;code&gt;rate(node_cpu_seconds_total[1m])&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt;: the start time&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt;: the end time&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step&lt;/code&gt;: the query resolution (for example, &lt;code&gt;30&lt;/code&gt; yields one data point every 30 seconds)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each query, the querier analyzes the &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; time range to compute a list of all known blocks containing at least one sample within the time range.
For each list of blocks per query, the querier computes a list of store-gateway instances holding the blocks. The querier sends a request to each matching store-gateway instance to fetch all samples for the series matching the &lt;code&gt;query&lt;/code&gt; within the &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; time range.&lt;/p&gt;
&lt;p&gt;The request sent to each store-gateway contains the list of block IDs that are expected to be queried, and the response sent back by the store-gateway to the querier contains the list of block IDs that were queried.
This list of block IDs might be a subset of the requested blocks, for example, when a recent blocks-resharding event occurs within the last few seconds.&lt;/p&gt;
&lt;p&gt;The querier runs a consistency check on responses received from the store-gateways to ensure all expected blocks have been queried.
If the expected blocks have not been queried, the querier retries fetching samples from missing blocks from different store-gateways up to &lt;code&gt;-store-gateway.sharding-ring.replication-factor&lt;/code&gt; (defaults to 3) times or maximum 3 times, whichever is lower.&lt;/p&gt;
&lt;p&gt;If the consistency check fails after all retry attempts, the query execution fails.
Query failure due to the querier not querying all blocks ensures the correctness of query results.&lt;/p&gt;
&lt;p&gt;If the query time range overlaps with the &lt;code&gt;-querier.query-ingesters-within&lt;/code&gt; duration, the querier also sends the request to ingesters.
The request to the ingesters fetches samples that have not yet been uploaded to the long-term storage or are not yet available for querying through the store-gateway.&lt;/p&gt;
&lt;p&gt;The configured period for &lt;code&gt;-querier.query-ingesters-within&lt;/code&gt; should be greater than both:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-querier.query-store-after&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the estimated minimum amount of time for the oldest samples stored in a block uploaded by ingester to be discovered and available for querying.
When running Grafana Mimir with the default configuration, the estimated minimum amount of time for the oldest sample in an uploaded block to be available for querying is &lt;code&gt;3h&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After all samples have been fetched from both the store-gateways and the ingesters, the querier runs the PromQL engine to execute the query and sends back the result to the client.&lt;/p&gt;
&lt;h3 id=&#34;connecting-to-store-gateways&#34;&gt;Connecting to store-gateways&lt;/h3&gt;
&lt;p&gt;You must configure the queriers with the same &lt;code&gt;-store-gateway.sharding-ring.*&lt;/code&gt; flags (or their respective YAML configuration parameters) that you use to configure the store-gateways so that the querier can access the store-gateway hash ring and discover the addresses of the store-gateways.&lt;/p&gt;
&lt;h3 id=&#34;connecting-to-ingesters&#34;&gt;Connecting to ingesters&lt;/h3&gt;
&lt;p&gt;You must configure the querier with the same &lt;code&gt;-ingester.ring.*&lt;/code&gt; flags (or their respective YAML configuration parameters) that you use to configure the ingesters so that the querier can access the ingester hash ring and discover the addresses of the ingesters.&lt;/p&gt;
&lt;h2 id=&#34;caching&#34;&gt;Caching&lt;/h2&gt;
&lt;p&gt;The querier supports the following cache:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#metadata-cache&#34;&gt;Metadata cache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Caching is optional, but highly recommended in a production environment.&lt;/p&gt;
&lt;h3 id=&#34;metadata-cache&#34;&gt;Metadata cache&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;../store-gateway/&#34;&gt;Store-gateways&lt;/a&gt; and queriers can use Memcached to cache the following bucket metadata:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List of tenants&lt;/li&gt;
&lt;li&gt;List of blocks per tenant&lt;/li&gt;
&lt;li&gt;Block &lt;code&gt;meta.json&lt;/code&gt; existence and content&lt;/li&gt;
&lt;li&gt;Block &lt;code&gt;deletion-mark.json&lt;/code&gt; existence and content&lt;/li&gt;
&lt;li&gt;Tenant &lt;code&gt;bucket-index.json.gz&lt;/code&gt; content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the metadata cache reduces the number of API calls to long-term storage and stops the number of the API calls that scale linearly with the number of querier and store-gateway replicas.&lt;/p&gt;
&lt;p&gt;To enable the metadata cache, set &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.backend&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;Currently, Mimir supports caching with the &lt;code&gt;memcached&lt;/code&gt; backend.&lt;/p&gt;
&lt;p&gt;The Memcached client includes additional configuration available via flags that begin with the prefix &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.memcached.*&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Additional flags for configuring the metadata cache begin with the prefix &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.*&lt;/code&gt;. By configuring the TTL to zero or a negative value, caching of given item type is disabled.&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;You should use the same Memcached backend cluster for both the store-gateways and queriers.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;querier-configuration&#34;&gt;Querier configuration&lt;/h2&gt;
&lt;p&gt;For details about querier configuration, refer to &lt;a href=&#34;../../../../configure/configuration-parameters/#querier&#34;&gt;querier&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-querier">Grafana Mimir querier&lt;/h1>
&lt;p>The querier is a stateless component that evaluates &lt;a href="https://prometheus.io/docs/prometheus/latest/querying/basics/" target="_blank" rel="noopener noreferrer">PromQL&lt;/a>
expressions by fetching time series and labels on the read path.&lt;/p>
&lt;p>The querier uses the &lt;a href="../store-gateway/">store-gateway&lt;/a> component to query the &lt;a href="../../../../get-started/about-grafana-mimir-architecture/#long-term-storage">long-term storage&lt;/a> and the &lt;a href="../ingester/">ingester&lt;/a> component to query recently written data.&lt;/p></description></item><item><title>Grafana Mimir query-frontend</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/query-frontend/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/query-frontend/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-query-frontend&#34;&gt;Grafana Mimir query-frontend&lt;/h1&gt;
&lt;p&gt;The query-frontend is a stateless component that provides the same API as the &lt;a href=&#34;../querier/&#34;&gt;querier&lt;/a&gt; and can be used to accelerate the read path.
Although the query-frontend is not required, we recommend that you deploy it.
When you deploy the query-frontend, you should make query requests to the query-frontend instead of the queriers.
The queriers are required within the cluster to execute the queries.&lt;/p&gt;
&lt;p&gt;The query-frontend internally holds queries in an internal queue.
In this situation, queriers act as workers that pull jobs from the queue, execute them, and return the results to the query-frontend for aggregation.
To connect the queriers with the query-frontends, configure queriers with the query-frontend address via the &lt;code&gt;-querier.frontend-address&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;We recommend that you run at least two query-frontend replicas for high-availability reasons.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;query-frontend-architecture.png&#34;
  alt=&#34;Query-frontend architecture&#34;/&gt;&lt;/p&gt;
&lt;p&gt;The following steps describe how a query moves through the query-frontend.&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 scenario doesn&amp;rsquo;t deploy a query-scheduler.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;A query-frontend receives a query.&lt;/li&gt;
&lt;li&gt;If the query is a range query, the query-frontend &lt;a href=&#34;#splitting&#34;&gt;splits it by time&lt;/a&gt; into multiple smaller queries that can be parallelized.&lt;/li&gt;
&lt;li&gt;The query-frontend checks the results cache. If the query result is in the cache, the query-frontend returns the cached result. If not, query execution continues according to the steps below.&lt;/li&gt;
&lt;li&gt;If &lt;a href=&#34;#about-query-sharding&#34;&gt;query-sharding&lt;/a&gt; is enabled, the query-frontend attempts to shard the query for further parallelization.&lt;/li&gt;
&lt;li&gt;The query-frontend places the query (or &lt;em&gt;queries&lt;/em&gt; if splitting or sharding of the initial query occurred) in an in-memory queue, where it waits to be picked up by a querier.&lt;/li&gt;
&lt;li&gt;A querier picks up the query from the queue and executes it. If the query was split or sharded into multiple subqueries, different queriers can pick up each of the individual queries.&lt;/li&gt;
&lt;li&gt;A querier or queriers return the result to query-frontend, which then aggregates and forwards the results to the client.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;
&lt;p&gt;This section describes the functions of the query-frontend.&lt;/p&gt;
&lt;h3 id=&#34;queueing&#34;&gt;Queueing&lt;/h3&gt;
&lt;p&gt;The query-frontend uses a queuing mechanism to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure that large queries that might cause an out-of-memory (OOM) error in the querier are retried if a query fails.
This enables administrators to under-provision memory for queries, or run more small queries in parallel, which helps to reduce the total cost of ownership.&lt;/li&gt;
&lt;li&gt;Prevent multiple large requests from being picked up by a single querier by distributing queries among all queriers using a first-in, first-out queue.&lt;/li&gt;
&lt;li&gt;Prevent a single tenant from denial-of-service-ing other tenants by fairly scheduling queries between tenants.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;splitting&#34;&gt;Splitting&lt;/h3&gt;
&lt;p&gt;The query-frontend can split long-range queries into multiple queries.
By default, the split interval is 24 hours.
The query-frontend executes these queries in parallel in downstream queriers and combines the results together.
Splitting prevents large multi-day or multi-month queries from causing out-of-memory errors in a querier and accelerates query execution.&lt;/p&gt;
&lt;h3 id=&#34;caching&#34;&gt;Caching&lt;/h3&gt;
&lt;p&gt;The query-frontend caches query results and reuses them on subsequent queries.
If the cached results are incomplete, the query-frontend calculates the required partial queries and executes them in parallel on downstream queriers.
The query-frontend can optionally align queries with their step parameter to improve the cacheability of the query results.
The result cache is backed by Memcached.&lt;/p&gt;
&lt;p&gt;Although aligning the step parameter to the query time range increases the performance of Grafana Mimir, it violates the &lt;a href=&#34;https://prometheus.io/blog/2021/05/03/introducing-prometheus-conformance-program/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;PromQL conformance&lt;/a&gt; of Grafana Mimir. If PromQL conformance is not a priority to you, you can enable step alignment by setting &lt;code&gt;-query-frontend.align-queries-with-step=true&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;about-query-sharding&#34;&gt;About query sharding&lt;/h3&gt;
&lt;p&gt;The query-frontend also provides &lt;a href=&#34;../../query-sharding/&#34;&gt;query sharding&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;why-query-frontend-scalability-is-limited&#34;&gt;Why query-frontend scalability is limited&lt;/h2&gt;
&lt;p&gt;The query-frontend scalability is limited by the configured number of workers per querier.&lt;/p&gt;
&lt;p&gt;When you don&amp;rsquo;t use the &lt;a href=&#34;../query-scheduler/&#34;&gt;query-scheduler&lt;/a&gt;, the query-frontend stores a queue of queries to execute.
A querier runs &lt;code&gt;-querier.max-concurrent&lt;/code&gt; workers and each worker connects to one of the query-frontend replicas to pull queries to execute.
A querier worker executes one query at a time.&lt;/p&gt;
&lt;p&gt;The connection between a querier worker and query-frontend is persistent.
After a connection is established, multiple queries are delivered through the connection, one by one.
To balance the number of workers connected to each query-frontend, the querier workers use a round-robin method to select the query-frontend replicas to connect to.&lt;/p&gt;
&lt;p&gt;If you run more query-frontend replicas than the number of workers per querier, the querier increases the number of internal workers to match the query-frontend replicas.
This ensures that all query-frontends have some of the workers connected, but introduces a scalability limit because the more query-frontend replicas you run, the higher is the number of workers running for each querier, regardless of the configured &lt;code&gt;-querier.max-concurrent&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;../query-scheduler/&#34;&gt;query-scheduler&lt;/a&gt; is an optional component that you can deploy to overcome the query-frontend scalability limitations.&lt;/p&gt;
&lt;h2 id=&#34;dns-configuration-and-readiness&#34;&gt;DNS configuration and readiness&lt;/h2&gt;
&lt;p&gt;When a query-frontend starts up, it does not immediately have queriers attached to it.
The &lt;a href=&#34;../../../http-api/#readiness-probe&#34;&gt;&lt;code&gt;/ready&lt;/code&gt; endpoint&lt;/a&gt; returns an HTTP 200 status code only when the query-frontend has at least one querier attached to it, and is then ready to serve queries.
Configure the &lt;code&gt;/ready&lt;/code&gt; endpoint as a healthcheck in your load balancer; otherwise, a query-frontend scale-out event might result in failed queries or high latency until queriers connect to the query-frontend.&lt;/p&gt;
&lt;p&gt;If you use query-frontend with query-scheduler, the &lt;code&gt;/ready&lt;/code&gt; endpoint reports an HTTP 200 status code only after the query-frontend connects to at least one query-scheduler.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-query-frontend">Grafana Mimir query-frontend&lt;/h1>
&lt;p>The query-frontend is a stateless component that provides the same API as the &lt;a href="../querier/">querier&lt;/a> and can be used to accelerate the read path.
Although the query-frontend is not required, we recommend that you deploy it.
When you deploy the query-frontend, you should make query requests to the query-frontend instead of the queriers.
The queriers are required within the cluster to execute the queries.&lt;/p></description></item><item><title>Grafana Mimir store-gateway</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/store-gateway/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/store-gateway/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-store-gateway&#34;&gt;Grafana Mimir store-gateway&lt;/h1&gt;
&lt;p&gt;The store-gateway component, which is stateful, queries blocks from &lt;a href=&#34;../../../../get-started/about-grafana-mimir-architecture/#long-term-storage&#34;&gt;long-term storage&lt;/a&gt;.
On the read path, the &lt;a href=&#34;../querier/&#34;&gt;querier&lt;/a&gt; and the &lt;a href=&#34;../ruler/&#34;&gt;ruler&lt;/a&gt; use the store-gateway when handling the query, whether the query comes from a user or from when a rule is being evaluated.&lt;/p&gt;
&lt;h2 id=&#34;bucket-index&#34;&gt;Bucket index&lt;/h2&gt;
&lt;p&gt;To find the right blocks to look up at query time, the store-gateway requires a view of the bucket in long-term storage.
The store-gateway keeps the bucket view updated using one of the following options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Periodically downloading the &lt;a href=&#34;../../bucket-index/&#34;&gt;bucket index&lt;/a&gt; (default)&lt;/li&gt;
&lt;li&gt;Periodically scanning the bucket&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;bucket-index-enabled-default&#34;&gt;Bucket index enabled (default)&lt;/h3&gt;
&lt;p&gt;To discover each tenant&amp;rsquo;s blocks and block deletion marks, at startup, store-gateways fetch the &lt;a href=&#34;../../bucket-index/&#34;&gt;bucket index&lt;/a&gt; from long-term storage for each tenant that belongs to their &lt;a href=&#34;#blocks-sharding-and-replication&#34;&gt;shard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For each discovered block, the store-gateway downloads the &lt;a href=&#34;#blocks-index-header&#34;&gt;index header&lt;/a&gt; to the local disk.
During this initial bucket-synchronization phase, the store-gateway’s &lt;code&gt;/ready&lt;/code&gt; readiness probe endpoint reports a not-ready status.&lt;/p&gt;
&lt;p&gt;For more information about the bucket index, refer to &lt;a href=&#34;../../bucket-index/&#34;&gt;bucket index&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Store-gateways periodically re-download the bucket index to obtain an updated view of the long-term storage and discover new blocks uploaded by ingesters and compactors, or deleted by compactors.&lt;/p&gt;
&lt;p&gt;It is possible that the compactor might have deleted blocks or marked others for deletion since the store-gateway last checked the block.
The store-gateway downloads the index header for new blocks, and offloads (deletes) the local copy of index header for deleted blocks.
You can configure the &lt;code&gt;-blocks-storage.bucket-store.sync-interval&lt;/code&gt; flag to control the frequency with which the store-gateway checks for changes in the long-term storage.&lt;/p&gt;
&lt;p&gt;When a query executes, the store-gateway downloads chunks, but it does not fully download the whole block; the store-gateway downloads only the portions of index and chunks that are required to run a given query.
To avoid the store-gateway having to re-download the index header during subsequent restarts, we recommend running the store-gateway with a persistent disk.
For example, if you&amp;rsquo;re running the Grafana Mimir cluster in Kubernetes, you can use a StatefulSet with a PersistentVolumeClaim for the store-gateways.&lt;/p&gt;
&lt;p&gt;For more information about the index-header, refer to &lt;a href=&#34;../../binary-index-header/&#34;&gt;Binary index-header documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;bucket-index-disabled&#34;&gt;Bucket index disabled&lt;/h3&gt;
&lt;p&gt;When the bucket index is disabled, the overall workflow is still nearly the same.
The difference occurs during the discovery phase of the blocks at startup, and during the periodic checks.
Iterations over the entire long-term storage download &lt;code&gt;meta.json&lt;/code&gt; metadata files while filtering out blocks that don&amp;rsquo;t belong to tenants in their shard.&lt;/p&gt;
&lt;h2 id=&#34;blocks-sharding-and-replication&#34;&gt;Blocks sharding and replication&lt;/h2&gt;
&lt;p&gt;The store-gateway uses blocks sharding to horizontally scale blocks in a large cluster.&lt;/p&gt;
&lt;p&gt;Blocks are replicated across multiple store-gateway instances based on a replication factor configured via &lt;code&gt;-store-gateway.sharding-ring.replication-factor&lt;/code&gt;.
The blocks replication is used to protect from query failures caused by some blocks not loaded by any store-gateway instance at a given time, such as in the event of a store-gateway failure or while restarting a store-gateway instance (for example, during a rolling update).&lt;/p&gt;
&lt;p&gt;Store-gateway instances build a &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; and shard and replicate blocks across the pool of store-gateway instances registered in the ring.&lt;/p&gt;
&lt;p&gt;Store-gateways continuously monitor the ring state.
When the ring topology changes, for example, when a new instance is added or removed, or the instance becomes healthy or unhealthy, each store-gateway instance resynchronizes the blocks assigned to its shard.
The store-gateway resynchronization process uses the block ID hash that matches the token ranges assigned to the instance within the ring.&lt;/p&gt;
&lt;p&gt;The store-gateway loads the index-header of each block that belongs to its store-gateway shard.
After the store-gateway loads a block’s index header, the block is ready to be queried by queriers.
When the querier queries blocks via a store-gateway, the response contains the list of queried block IDs.
If a querier attempts to query a block that the store-gateway has not loaded, the querier retries the query on a different store-gateway up to the &lt;code&gt;-store-gateway.sharding-ring.replication-factor&lt;/code&gt; value, which by default is &lt;code&gt;3&lt;/code&gt;.
The query fails if the block can&amp;rsquo;t be successfully queried from any replica.&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;You must configure the &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; via the &lt;code&gt;-store-gateway.sharding-ring.*&lt;/code&gt; flags or their respective YAML configuration parameters.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;sharding-strategy&#34;&gt;Sharding strategy&lt;/h3&gt;
&lt;p&gt;The store-gateway uses shuffle-sharding to divide the blocks of each tenant across a subset of store-gateway instances.&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;When shuffle-sharding is in use, only a subset of store-gateway instances load the blocks of a tenant.&lt;/p&gt;
&lt;p&gt;This confines blast radius of issues introduced by the tenant&amp;rsquo;s workload to its shard instances.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;-store-gateway.tenant-shard-size&lt;/code&gt; flag (or their respective YAML configuration parameters) determines the default number of store-gateway instances per tenant.
The &lt;code&gt;store_gateway_tenant_shard_size&lt;/code&gt; in the limits overrides can override the shard size on a per-tenant basis.&lt;/p&gt;
&lt;p&gt;The default &lt;code&gt;-store-gateway.tenant-shard-size&lt;/code&gt; value is 0, which means that tenant&amp;rsquo;s blocks are sharded across all store-gateway instances.&lt;/p&gt;
&lt;p&gt;For more information about shuffle sharding, refer to &lt;a href=&#34;../../../../configure/configure-shuffle-sharding/&#34;&gt;configure shuffle sharding&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;auto-forget&#34;&gt;Auto-forget&lt;/h3&gt;
&lt;p&gt;Store-gateways include an auto-forget feature that they can use to unregister an instance from another store-gateway&amp;rsquo;s ring when a store-gateway does not properly shut down.
Under normal conditions, when a store-gateway instance shuts down, it automatically unregisters from the ring. However, in the event of a crash or node failure, the instance might not properly unregister, which can leave a spurious entry in the ring.&lt;/p&gt;
&lt;p&gt;The auto-forget feature works as follows: when an healthy store-gateway instance identifies an instance in the ring that is unhealthy for longer than 10 times the configured &lt;code&gt;-store-gateway.sharding-ring.heartbeat-timeout&lt;/code&gt; value, the healthy instance removes the unhealthy instance from the ring.&lt;/p&gt;
&lt;p&gt;The store-gateway auto-forget feature can be disabled by setting &lt;code&gt;-store-gateway.sharding-ring.auto-forget-enabled=false&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;zone-awareness&#34;&gt;Zone-awareness&lt;/h3&gt;
&lt;p&gt;Store-gateway replication optionally supports &lt;a href=&#34;../../../../configure/configure-zone-aware-replication/&#34;&gt;zone-awareness&lt;/a&gt;. When you enable zone-aware replication and the blocks replication factor is greater than 1, each block is replicated across store-gateway instances located in different availability zones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To enable zone-aware replication for the store-gateways&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Configure the availability zone for each store-gateway via the &lt;code&gt;-store-gateway.sharding-ring.instance-availability-zone&lt;/code&gt; CLI flag or its respective YAML configuration parameter.&lt;/li&gt;
&lt;li&gt;Enable blocks zone-aware replication via the &lt;code&gt;-store-gateway.sharding-ring.zone-awareness-enabled&lt;/code&gt; CLI flag or its respective YAML configuration parameter.
Set this zone-aware replication flag on store-gateways, queriers, and rulers.&lt;/li&gt;
&lt;li&gt;To apply the new configuration, roll out store-gateways, queriers, and rulers.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;waiting-for-stable-ring-at-startup&#34;&gt;Waiting for stable ring at startup&lt;/h3&gt;
&lt;p&gt;If a cluster cold starts or scales up to two or more store-gateway instances simultaneously, the store-gateways could start at different times. As a result, the store-gateway runs the initial blocks synchronization based on a different state of the hash ring.&lt;/p&gt;
&lt;p&gt;For example, in the event of a cold start, the first store-gateway that joins the ring might load all blocks because the sharding logic runs based on the current state of the ring, which contains one single store-gateway.&lt;/p&gt;
&lt;p&gt;To reduce the likelihood of store-gateways starting at different times, you can configure the store-gateway to wait for a stable ring at startup. A ring is considered stable when no instance is added or removed from the ring for the minimum duration specified in the &lt;code&gt;-store-gateway.sharding-ring.wait-stability-min-duration&lt;/code&gt; flag. If the ring continues to change after reaching the maximum duration specified in the &lt;code&gt;-store-gateway.sharding-ring.wait-stability-max-duration&lt;/code&gt; flag, the store-gateway stops waiting for a stable ring and proceeds starting up.&lt;/p&gt;
&lt;p&gt;To enable waiting for the ring to be stable at startup, start the store-gateway with &lt;code&gt;-store-gateway.sharding-ring.wait-stability-min-duration=1m&lt;/code&gt;, which is the recommended value for production systems.&lt;/p&gt;
&lt;h2 id=&#34;blocks-index-header&#34;&gt;Blocks index-header&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../../binary-index-header/&#34;&gt;index-header&lt;/a&gt; is a subset of the block index that the store-gateway downloads from long-term storage and keeps on the local disk.
Keeping the index-header on the local disk makes query execution faster.&lt;/p&gt;
&lt;h3 id=&#34;index-header-lazy-loading&#34;&gt;Index-header lazy loading&lt;/h3&gt;
&lt;p&gt;By default, a store-gateway downloads the index-headers to disk and doesn&amp;rsquo;t load them to memory until required.
When required by a query, index-headers are memory-mapped and automatically released by the store-gateway after the amount of inactivity time you specify in &lt;code&gt;-blocks-storage.bucket-store.index-header.lazy-loading-idle-timeout&lt;/code&gt; has passed.&lt;/p&gt;
&lt;p&gt;Grafana Mimir provides a configuration flag &lt;code&gt;-blocks-storage.bucket-store.index-header.lazy-loading-enabled=false&lt;/code&gt; to disable index-header lazy loading.
When disabled, the store-gateway memory-maps all index-headers, which provides faster access to the data in the index-header.
However, in a cluster with a large number of blocks, each store-gateway might have a large amount of memory-mapped index-headers, regardless of how frequently they are used at query time.&lt;/p&gt;
&lt;h2 id=&#34;caching&#34;&gt;Caching&lt;/h2&gt;
&lt;p&gt;The store-gateway supports the following type of caches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#index-cache&#34;&gt;Index cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#chunks-cache&#34;&gt;Chunks cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#metadata-cache&#34;&gt;Metadata cache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We recommend that you use caching in a production environment.
For more information about configuring the cache, refer to &lt;a href=&#34;../../../../manage/run-production-environment/production-tips/#caching&#34;&gt;production tips&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;index-cache&#34;&gt;Index cache&lt;/h3&gt;
&lt;p&gt;The store-gateway can use a cache to accelerate series and label lookups from block indexes. The store-gateway supports the following backends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;inmemory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memcached&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;in-memory-index-cache&#34;&gt;In-memory index cache&lt;/h4&gt;
&lt;p&gt;By default, the &lt;code&gt;inmemory&lt;/code&gt; index cache is enabled.&lt;/p&gt;
&lt;p&gt;Consider the following trade-offs of using the in-memory index cache:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pros: There is no latency.&lt;/li&gt;
&lt;li&gt;Cons: When the replication factor is &amp;gt; 1, then the data that resides in the memory of the store-gateway will be duplicated among different instances. This leads to an increase in overall memory usage and a reduced cache hit ratio.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can configure the index cache max size using the &lt;code&gt;-blocks-storage.bucket-store.index-cache.inmemory.max-size-bytes&lt;/code&gt; flag or its respective YAML configuration parameter.&lt;/p&gt;
&lt;h4 id=&#34;memcached-index-cache&#34;&gt;Memcached index cache&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;memcached&lt;/code&gt; index cache uses &lt;a href=&#34;https://memcached.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Memcached&lt;/a&gt; as the cache backend.&lt;/p&gt;
&lt;p&gt;Consider the following trade-offs of using the Memcached index cache:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pros: You can scale beyond a single node&amp;rsquo;s memory by creating a Memcached cluster, that is shared by multiple store-gateway instances.&lt;/li&gt;
&lt;li&gt;Cons: The system experiences higher latency in the cache round trip compared to the latency experienced when using in-memory cache.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Memcached client uses a jump hash algorithm to shard cached entries across a cluster of Memcached servers.
Because the memcached client uses a jump hash algorithm, ensure that memcached servers are not located behind a load balancer, and configure the address of the memcached servers so that servers are added to or removed from the end of the list whenever a scale up or scale down occurs.&lt;/p&gt;
&lt;p&gt;For example, if you&amp;rsquo;re running Memcached in Kubernetes, you might:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Deploy your Memcached cluster using a &lt;a href=&#34;https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;StatefulSet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;a href=&#34;https://kubernetes.io/docs/concepts/services-networking/service/#headless-services&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;headless service&lt;/a&gt; for Memcached StatefulSet.&lt;/li&gt;
&lt;li&gt;Configure the Mimir&amp;rsquo;s Memcached client address using the &lt;code&gt;dnssrvnoa&#43;&lt;/code&gt; &lt;a href=&#34;../../../../configure/about-dns-service-discovery/&#34;&gt;service discovery&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;To configure the Memcached backend&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;-blocks-storage.bucket-store.index-cache.backend=memcached&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;-blocks-storage.bucket-store.index-cache.memcached.addresses&lt;/code&gt; flag to set the address of the Memcached service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&#34;../../../../configure/about-dns-service-discovery/&#34;&gt;DNS service discovery&lt;/a&gt; resolves the addresses of the Memcached servers.&lt;/p&gt;
&lt;h3 id=&#34;chunks-cache&#34;&gt;Chunks cache&lt;/h3&gt;
&lt;p&gt;The store-gateway can also use a cache to store &lt;a href=&#34;../../../glossary/#chunk&#34;&gt;chunks&lt;/a&gt; that are fetched from long-term storage.
Chunks contain actual samples, and can be reused if a query hits the same series for the same time range.
Chunks can only be cached in Memcached.&lt;/p&gt;
&lt;p&gt;To enable chunks cache, set &lt;code&gt;-blocks-storage.bucket-store.chunks-cache.backend=memcached&lt;/code&gt;.
You can configure the Memcached client via flags that include the prefix &lt;code&gt;-blocks-storage.bucket-store.chunks-cache.memcached.*&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;There are additional low-level flags that begin with the prefix &lt;code&gt;-blocks-storage.bucket-store.chunks-cache.*&lt;/code&gt; that you can use to configure chunks cache.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;metadata-cache&#34;&gt;Metadata cache&lt;/h3&gt;
&lt;p&gt;Store-gateways and &lt;a href=&#34;../querier/&#34;&gt;queriers&lt;/a&gt; can use memcached to cache the following bucket metadata:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List of tenants&lt;/li&gt;
&lt;li&gt;List of blocks per tenant&lt;/li&gt;
&lt;li&gt;Block &lt;code&gt;meta.json&lt;/code&gt; existence and content&lt;/li&gt;
&lt;li&gt;Block &lt;code&gt;deletion-mark.json&lt;/code&gt; existence and content&lt;/li&gt;
&lt;li&gt;Tenant &lt;code&gt;bucket-index.json.gz&lt;/code&gt; content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the metadata cache reduces the number of API calls to long-term storage and eliminates API calls that scale linearly as the number of querier and store-gateway replicas increases.&lt;/p&gt;
&lt;p&gt;To enable metadata cache, set &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.backend&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;Mimir only supports the &lt;code&gt;memcached&lt;/code&gt; backend for the metadata cache.&lt;/p&gt;
&lt;p&gt;The Memcached client includes additional configuration available via flags that begin with the prefix &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.memcached.*&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Additional flags for configuring metadata cache begin with the prefix &lt;code&gt;-blocks-storage.bucket-store.metadata-cache.*&lt;/code&gt;. By configuring TTL to zero or a negative value, caching of given item type is disabled.&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;You should use the same Memcached backend cluster for both the store-gateways and queriers.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;store-gateway-http-endpoints&#34;&gt;Store-gateway HTTP endpoints&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /store-gateway/ring&lt;/code&gt;&lt;br /&gt;
Displays the status of the store-gateways ring, including the tokens owned by each store-gateway and an option to remove (or forget) instances from the ring.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;store-gateway-configuration&#34;&gt;Store-gateway configuration&lt;/h2&gt;
&lt;p&gt;For more information about store-gateway configuration, refer to &lt;a href=&#34;../../../../configure/configuration-parameters/#store_gateway&#34;&gt;store_gateway&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-store-gateway">Grafana Mimir store-gateway&lt;/h1>
&lt;p>The store-gateway component, which is stateful, queries blocks from &lt;a href="../../../../get-started/about-grafana-mimir-architecture/#long-term-storage">long-term storage&lt;/a>.
On the read path, the &lt;a href="../querier/">querier&lt;/a> and the &lt;a href="../ruler/">ruler&lt;/a> use the store-gateway when handling the query, whether the query comes from a user or from when a rule is being evaluated.&lt;/p></description></item><item><title>(Optional) Grafana Mimir Alertmanager</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/alertmanager/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/alertmanager/</guid><content><![CDATA[&lt;h1 id=&#34;optional-grafana-mimir-alertmanager&#34;&gt;(Optional) Grafana Mimir Alertmanager&lt;/h1&gt;
&lt;p&gt;The Mimir Alertmanager adds multi-tenancy support and horizontal scalability to the &lt;a href=&#34;https://prometheus.io/docs/alerting/alertmanager/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus Alertmanager&lt;/a&gt;.
The Mimir Alertmanager is an optional component that accepts alert notifications from the &lt;a href=&#34;../ruler/&#34;&gt;Mimir ruler&lt;/a&gt;.
The Alertmanager deduplicates and groups alert notifications, and routes them to a notification channel, such as email, PagerDuty, or OpsGenie.&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;To run Mimir Alertmanager as a part of &lt;a href=&#34;../../deployment-modes/#monolithic-mode&#34;&gt;monolithic deployment&lt;/a&gt;, run Mimir with the option &lt;code&gt;-target=all,alertmanager&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;multi-tenancy&#34;&gt;Multi-tenancy&lt;/h2&gt;
&lt;p&gt;Like other Mimir components, multi-tenancy in the Mimir Alertmanager uses the tenant ID header.
Each tenant has an isolated alert routing configuration and Alertmanager UI.&lt;/p&gt;
&lt;h3 id=&#34;tenant-configurations&#34;&gt;Tenant configurations&lt;/h3&gt;
&lt;p&gt;Each tenant has an Alertmanager configuration that defines notifications receivers and alerting routes.
The Mimir Alertmanager uses the same &lt;a href=&#34;https://prometheus.io/docs/alerting/latest/configuration/#configuration-file&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;configuration file&lt;/a&gt; that the Prometheus Alertmanager uses.&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;The Mimir Alertmanager exposes the configuration API according to the path set by the &lt;code&gt;-server.path-prefix&lt;/code&gt; flag.
It doesn&amp;rsquo;t use the path set by the &lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;If you run Mimir with the default configuration, &lt;code&gt;-server.path-prefix&lt;/code&gt;, where the default value is &lt;code&gt;/&lt;/code&gt;, then only set the hostname for the &lt;code&gt;--address&lt;/code&gt; flag of the &lt;code&gt;mimirtool&lt;/code&gt; command; don&amp;rsquo;t set a path-specific address.
For example, &lt;code&gt;/&lt;/code&gt; is correct, and &lt;code&gt;/alertmanager&lt;/code&gt; is incorrect.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;You can validate a configuration file using the &lt;code&gt;mimirtool&lt;/code&gt; command:&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;mimirtool alertmanager verify &amp;lt;ALERTMANAGER CONFIGURATION FILE&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following sample command shows how to upload a tenant&amp;rsquo;s Alertmanager configuration using &lt;code&gt;mimirtool&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;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;mimirtool alertmanager load &amp;lt;ALERTMANAGER CONFIGURATION FILE&amp;gt;  \
  --address=&amp;lt;ALERTMANAGER URL&amp;gt;
  --id=&amp;lt;TENANT ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following sample command shows how to retrieve a tenant&amp;rsquo;s Alertmanager configuration using &lt;code&gt;mimirtool&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;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;mimirtool alertmanager get \
  --address=&amp;lt;ALERTMANAGER URL&amp;gt;
  --id=&amp;lt;TENANT ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following sample commands shows how to delete a tenant&amp;rsquo;s Alertmanager configuration using &lt;code&gt;mimirtool&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;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;mimirtool alertmanager delete \
  --address=&amp;lt;ALERTMANAGER URL&amp;gt;
  --id=&amp;lt;TENANT ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After the tenant uploads an Alertmanager configuration, the tenant can access the Alertmanager UI at the &lt;code&gt;/alertmanager&lt;/code&gt; endpoint.&lt;/p&gt;
&lt;h4 id=&#34;fallback-configuration&#34;&gt;Fallback configuration&lt;/h4&gt;
&lt;p&gt;When a tenant doesn&amp;rsquo;t have a Alertmanager configuration, the Grafana Mimir Alertmanager uses a fallback configuration.
By default, there is always a fallback configuration set.
You can overwrite the default fallback configuration via the &lt;code&gt;-alertmanager.configs.fallback&lt;/code&gt; command-line flag.&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;Without a fallback configuration or a tenant specific configuration, the Alertmanager UI is inaccessible and ruler notifications for that tenant fail.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;tenant-limits&#34;&gt;Tenant limits&lt;/h3&gt;
&lt;p&gt;The Grafana Mimir Alertmanager has a number of per-tenant limits documented in &lt;a href=&#34;../../../../configure/configuration-parameters/#limits&#34;&gt;&lt;code&gt;limits&lt;/code&gt;&lt;/a&gt;.
Each Mimir Alertmanager limit configuration parameter has an &lt;code&gt;alertmanager&lt;/code&gt; prefix.&lt;/p&gt;
&lt;h2 id=&#34;alertmanager-ui&#34;&gt;Alertmanager UI&lt;/h2&gt;
&lt;p&gt;The Mimir Alertmanager exposes the same web UI as the Prometheus Alertmanager at the &lt;code&gt;/alertmanager&lt;/code&gt; endpoint.&lt;/p&gt;
&lt;p&gt;When running Grafana Mimir with multi-tenancy enabled, the Alertmanager requires that any HTTP request include the tenant ID header.
Tenants only see alerts sent to their Alertmanager.&lt;/p&gt;
&lt;p&gt;For a complete reference of the tenant ID header and Alertmanager endpoints, refer to &lt;a href=&#34;../../../http-api/&#34;&gt;HTTP API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can configure the HTTP path prefix for the UI and the HTTP API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; configures the path prefix for Alertmanager endpoints.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-alertmanager.web.external-url&lt;/code&gt; configures the source URLs generated in Alertmanager alerts and from where to fetch web assets.&lt;/li&gt;
&lt;/ul&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;Unless you are using a reverse proxy in front of the Alertmanager API that rewrites routes, the path prefix set in &lt;code&gt;-alertmanager.web.external-url&lt;/code&gt; must match the path prefix set in &lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; which is &lt;code&gt;/alertmanager&lt;/code&gt; by default.&lt;/p&gt;
&lt;p&gt;If the path prefixes don&amp;rsquo;t match, HTTP requests routing might not work as expected.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;using-a-reverse-proxy&#34;&gt;Using a reverse proxy&lt;/h3&gt;
&lt;p&gt;When using a reverse proxy, use the following settings when you configure the HTTP path:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; to match the proxy path in your reverse proxy configuration.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;-alertmanager.web.external-url&lt;/code&gt; to the URL served by your reverse proxy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;templating&#34;&gt;Templating&lt;/h2&gt;
&lt;p&gt;The Mimir Alertmanager adds some custom template functions to the default ones of the Prometheus Alertmanager.&lt;/p&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Function&lt;/th&gt;
              &lt;th&gt;Params&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;tenantID&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;-&lt;/td&gt;
              &lt;td&gt;Returns ID of the tenant the alert belongs to.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;queryFromGeneratorURL&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;generator_url&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Returns the URL decoded query from &lt;code&gt;GeneratorURL&lt;/code&gt; of an alert set by a Prometheus. Example: &lt;code&gt;{{ queryFromGeneratorURL (index .Alerts 0).GeneratorURL }}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;grafanaExploreURL&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;grafana_URL&lt;/code&gt;,&lt;code&gt;datasource&lt;/code&gt;,&lt;code&gt;from&lt;/code&gt;,&lt;code&gt;to&lt;/code&gt;,&lt;code&gt;expr&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Returns link to Grafana explore with range query based on the input parameters. Example: &lt;code&gt;{{ grafanaExploreURL &amp;quot;https://foo.bar&amp;quot; &amp;quot;xyz&amp;quot; &amp;quot;now-12h&amp;quot; &amp;quot;now&amp;quot; (queryFromGeneratorURL (index .Alerts 0).GeneratorURL) }}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h2 id=&#34;sharding-and-replication&#34;&gt;Sharding and replication&lt;/h2&gt;
&lt;p&gt;The Alertmanager shards and replicates alerts by tenant.
Sharding requires that the number of Alertmanager replicas is greater-than or equal-to the replication factor configured by the &lt;code&gt;-alertmanager.sharding-ring.replication-factor&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;Grafana Mimir Alertmanager replicas use a &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; that is stored in the KV store to discover their peers.
This means that any Mimir Alertmanager replica can respond to any API or UI request for any tenant.
If the Mimir Alertmanager replica receiving the HTTP request doesn&amp;rsquo;t own the tenant to which the request belongs, the request is internally routed to the appropriate replica.&lt;/p&gt;
&lt;p&gt;To configure the Alertmanagers&amp;rsquo; hash ring, refer to &lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;configuring hash rings&lt;/a&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;When running with a single tenant, scaling the number of replicas to be greater than the replication factor offers no benefits as the Mimir Alertmanager shards by tenant and not individual alerts.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;state&#34;&gt;State&lt;/h3&gt;
&lt;p&gt;The Mimir Alertmanager stores the alerts state on local disk at the location configured using &lt;code&gt;-alertmanager.storage.path&lt;/code&gt;.&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;When running the Mimir Alertmanager without replication, ensure persistence of the &lt;code&gt;-alertmanager.storage.path&lt;/code&gt; directory to avoid losing alert state.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The Mimir Alertmanager also periodically stores the alert state in the storage backend configured with &lt;code&gt;-alertmanager-storage.backend&lt;/code&gt;.
When an Alertmanager starts, it attempts to load the alerts state for a given tenant from other Alertmanager replicas. If the load from other Alertmanager replicas fails, the Alertmanager falls back to the state that is periodically stored in the storage backend.&lt;/p&gt;
&lt;p&gt;In the event of a cluster outage, this fallback mechanism recovers the backup of the previous state. Because backups are taken periodically, this fallback mechanism does not guarantee that the most recent state is restored.&lt;/p&gt;
&lt;h2 id=&#34;ruler-configuration&#34;&gt;Ruler configuration&lt;/h2&gt;
&lt;p&gt;You must configure the &lt;a href=&#34;../ruler/&#34;&gt;ruler&lt;/a&gt; with the addresses of Alertmanagers via the &lt;code&gt;-ruler.alertmanager-url&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;Point the address to Alertmanager’s API.
You can configure Alertmanager’s API prefix via the &lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; flag, which defaults to &lt;code&gt;/alertmanager&lt;/code&gt;.
For example, if Alertmanager is listening at &lt;code&gt;http://mimir-alertmanager.namespace.svc.cluster.local&lt;/code&gt; and it is using the default API prefix, set &lt;code&gt;-ruler.alertmanager-url&lt;/code&gt; to &lt;code&gt;http://mimir-alertmanager.namespace.svc.cluster.local/alertmanager&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;enable-utf-8&#34;&gt;Enable UTF-8&lt;/h2&gt;
&lt;p&gt;In effort to support alerts from &lt;a href=&#34;https://opentelemetry.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenTelemetry&lt;/a&gt; (OTel) data, &lt;a href=&#34;https://prometheus.io/docs/alerting/alertmanager/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus Alertmanager&lt;/a&gt; has added support for UTF-8. This is supported as an opt-in feature for the Grafana Mimir Alertmanager in Mimir versions 2.12 and later.&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;Enabling and then disabling UTF-8 strict mode can break existing tenant configurations if tenants added UTF-8 characters to their Alertmanager configuration while it was enabled. Once enabled, disable UTF-8 strict mode with caution.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;For new Mimir installations, enable support for UTF-8 before creating any tenant configurations. You can do this by changing &lt;a href=&#34;../../../../configure/configuration-parameters/#alertmanager&#34;&gt;&lt;code&gt;utf8-strict-mode-enabled&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For existing Mimir installations, there are a number of breaking changes that might affect existing tenant configurations. Follow these instructions to ensure all existing tenant configurations are compatible with UTF-8 before enabling it.&lt;/p&gt;
&lt;h3 id=&#34;what-are-the-breaking-changes&#34;&gt;What are the breaking changes?&lt;/h3&gt;
&lt;p&gt;In order to support UTF-8, Alertmanager has added a new parser for label matchers (often abbreviated as matchers), which has a number of breaking changes.&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;If you are unfamiliar with what matchers are or how they are used in a tenant configuration, you can find more information about them in the &lt;a href=&#34;https://prometheus.io/docs/alerting/latest/configuration&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus Alertmanager documentation&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Grafana Mimir provides a number of tools to help you identify whether any existing tenant configurations are affected by these breaking changes, and to migrate any affected tenant configurations in a way that is backwards-compatible, doesn&amp;rsquo;t change the behavior of existing matchers, and works even in Mimir installations that do not have UTF-8 enabled.&lt;/p&gt;
&lt;h3 id=&#34;identify-affected-tenant-configurations&#34;&gt;Identify affected tenant configurations&lt;/h3&gt;
&lt;p&gt;To identify affected tenant configurations, take the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Make sure Mimir is running version 2.12 or later with debug-level logging enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To identify any tenant configurations that are incompatible with UTF-8 (meaning the tenant configuration fails to load and the &lt;a href=&#34;#fallback-configuration&#34;&gt;fallback configuration&lt;/a&gt; is used instead), search Mimir server logs for lines containing &lt;code&gt;Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible&lt;/code&gt;. Each log line includes the invalid matcher from the tenant configuration and the ID of the affected tenant. 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;msg=&amp;#34;Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue.&amp;#34; input=&amp;#34;foo=&amp;#34; err=&amp;#34;end of input: expected label value&amp;#34; suggestion=&amp;#34;foo=\&amp;#34;\&amp;#34;&amp;#34; user=&amp;#34;1&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the tenant with User ID &lt;code&gt;1&lt;/code&gt; has an incompatible matcher in their tenant configuration &lt;code&gt;foo=&lt;/code&gt; and should to be changed to the suggestion &lt;code&gt;foo=&amp;quot;&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To identify any tenant configurations that are compatible with UTF-8 but contain matchers that might change in behavior when its enabled, search Mimir server logs for lines containing &lt;code&gt;Matchers input has disagreement&lt;/code&gt;. Disagreement occurs when a matcher is valid, but due to adding support for UTF-8, it can behave differently when UTF-8 is enabled.&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;msg=&amp;#34;Matchers input has disagreement&amp;#34; input=&amp;#34;foo=\&amp;#34;\\xf0\\x9f\\x99\\x82\&amp;#34;&amp;#34; user=&amp;#34;1&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&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;It is possible for a tenant configuration to be both incompatible with UTF-8 and have disagreement, as an individual tenant configuration can contain a large number of matchers across different routes and inhibition rules.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;fix-tenant-configurations&#34;&gt;Fix tenant configurations&lt;/h3&gt;
&lt;p&gt;To fix any identified tenant configurations, take the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use the &lt;code&gt;migrate-utf8&lt;/code&gt; &lt;a href=&#34;../../../../manage/tools/mimirtool/#migrate-alertmanager-configuration-for-utf-8-in-mimir-212-and-later&#34;&gt;command&lt;/a&gt; in mimirtool to fix any tenant configurations that are incompatible with UTF-8. This command can migrate existing tenant configurations in a way that is backwards-compatible, doesn&amp;rsquo;t change the behavior of existing matchers, and works even in Mimir installations that don&amp;rsquo;t have UTF-8 enabled. If you cannot use mimirtool, you can edit tenant configurations by hand through applying each suggestion from the Mimir server logs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You must look at tenant configurations that have disagreement on a case-by-case basis. Depending on the nature of the disagreement, you might not need to fix a matcher with disagreement. For example &lt;code&gt;\xf0\x9f\x99\x82&lt;/code&gt; is the byte sequence for the 🙂 emoji. If the intention is to match a literal 🙂 emoji then no change is required. However, if the intention is to match the literal &lt;code&gt;\xf0\x9f\x99\x82&lt;/code&gt; then you need to change the matcher to use &lt;code&gt;\\xf0\\x9f\\x99\\x82&lt;/code&gt; instead.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;It&amp;rsquo;s rare to find cases of disagreement in a tenant configuration, as most tenants do not need to match alerts that contain literal UTF-8 byte sequences in their labels.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;final-steps&#34;&gt;Final steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;After identifying and fixing all affected tenant configurations, check the Mimir server logs again to make sure you haven&amp;rsquo;t missed any tenant configurations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To enable UTF-8, set &lt;a href=&#34;../../../../configure/configuration-parameters/#alertmanager&#34;&gt;&lt;code&gt;utf8-strict-mode-enabled&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;true&lt;/code&gt;. You must restart Mimir for the changes to take effect.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To confirm UTF-8 is enabled, search for &lt;code&gt;Starting Alertmanager in UTF-8 strict mode&lt;/code&gt; in the Mimir server logs. If you find &lt;code&gt;Starting Alertmanager in classic mode&lt;/code&gt; instead then UTF-8 is not enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any incompatible tenant configurations will fail to load. To identify if any tenant configurations are failing to load, search the Mimir server logs for lines containing &lt;code&gt;error applying config&lt;/code&gt;, or query the &lt;code&gt;cortex_alertmanager_config_last_reload_successful&lt;/code&gt; gauge for &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can disable debug-level logging.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="optional-grafana-mimir-alertmanager">(Optional) Grafana Mimir Alertmanager&lt;/h1>
&lt;p>The Mimir Alertmanager adds multi-tenancy support and horizontal scalability to the &lt;a href="https://prometheus.io/docs/alerting/alertmanager/" target="_blank" rel="noopener noreferrer">Prometheus Alertmanager&lt;/a>.
The Mimir Alertmanager is an optional component that accepts alert notifications from the &lt;a href="../ruler/">Mimir ruler&lt;/a>.
The Alertmanager deduplicates and groups alert notifications, and routes them to a notification channel, such as email, PagerDuty, or OpsGenie.&lt;/p></description></item><item><title>(Optional) Grafana Mimir overrides-exporter</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/overrides-exporter/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/overrides-exporter/</guid><content><![CDATA[&lt;h1 id=&#34;optional-grafana-mimir-overrides-exporter&#34;&gt;(Optional) Grafana Mimir overrides-exporter&lt;/h1&gt;
&lt;p&gt;Grafana Mimir supports applying overrides on a per-tenant basis.
A number of overrides configure limits that prevent a single tenant from using too many resources.
The overrides-exporter component exposes limits as Prometheus metrics so that operators can understand how close tenants are to their limits.&lt;/p&gt;
&lt;p&gt;For more information about configuring overrides, refer to &lt;a href=&#34;../../../../configure/about-runtime-configuration/&#34;&gt;Runtime configuration file&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;running-the-overrides-exporter&#34;&gt;Running the overrides-exporter&lt;/h2&gt;
&lt;p&gt;The overrides-exporter must be explicitly enabled.&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;The metrics emitted by the overrides-exporter have high cardinality.
It&amp;rsquo;s recommended to run only a single replica of the overrides-exporter to limit that cardinality.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;With a &lt;code&gt;runtime.yaml&lt;/code&gt; file as follows:&lt;/p&gt;
&lt;!-- prettier-ignore-start --&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;# file: runtime.yaml
# In this example, we&amp;#39;re overriding ingestion limits for a single tenant.
overrides:
  &amp;#34;user1&amp;#34;:
    ingestion_burst_size: 350000
    ingestion_rate: 350000
    max_global_series_per_metric: 300000
    max_global_series_per_user: 300000&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;!-- prettier-ignore-end --&gt;
&lt;p&gt;Run the overrides-exporter by providing the &lt;code&gt;-target&lt;/code&gt;, and &lt;code&gt;-runtime-config.file&lt;/code&gt; flags:&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;mimir -target=overrides-exporter -runtime-config.file=runtime.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After the overrides-exporter starts, you can to use &lt;code&gt;curl&lt;/code&gt; to inspect the tenant overrides:&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 -s http://localhost:8080/metrics | grep cortex_limits_overrides&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output metrics look similar to the following:&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;console&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-console&#34;&gt;# HELP cortex_limits_overrides Resource limit overrides applied to tenants
# TYPE cortex_limits_overrides gauge
cortex_limits_overrides{limit_name=&amp;#34;ingestion_burst_size&amp;#34;,user=&amp;#34;user1&amp;#34;} 350000
cortex_limits_overrides{limit_name=&amp;#34;ingestion_rate&amp;#34;,user=&amp;#34;user1&amp;#34;} 350000
cortex_limits_overrides{limit_name=&amp;#34;max_global_series_per_metric&amp;#34;,user=&amp;#34;user1&amp;#34;} 300000
cortex_limits_overrides{limit_name=&amp;#34;max_global_series_per_user&amp;#34;,user=&amp;#34;user1&amp;#34;} 300000&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With these metrics, you can set up alerts to know when tenants are close to hitting their limits
before they exceed them.&lt;/p&gt;
]]></content><description>&lt;h1 id="optional-grafana-mimir-overrides-exporter">(Optional) Grafana Mimir overrides-exporter&lt;/h1>
&lt;p>Grafana Mimir supports applying overrides on a per-tenant basis.
A number of overrides configure limits that prevent a single tenant from using too many resources.
The overrides-exporter component exposes limits as Prometheus metrics so that operators can understand how close tenants are to their limits.&lt;/p></description></item><item><title>(Optional) Grafana Mimir query-scheduler</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/query-scheduler/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/query-scheduler/</guid><content><![CDATA[&lt;h1 id=&#34;optional-grafana-mimir-query-scheduler&#34;&gt;(Optional) Grafana Mimir query-scheduler&lt;/h1&gt;
&lt;p&gt;The query-scheduler is an optional, stateless component that retains a queue of queries to execute, and distributes the workload to available &lt;a href=&#34;../querier/&#34;&gt;queriers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;query-scheduler-architecture.png&#34;
  alt=&#34;Query-scheduler architecture&#34;/&gt;&lt;/p&gt;
&lt;p&gt;The following flow describes how a query moves through a Grafana Mimir cluster:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;a href=&#34;../query-frontend/&#34;&gt;query-frontend&lt;/a&gt; receives queries, and then either splits and shards them, or serves them from the cache.&lt;/li&gt;
&lt;li&gt;The query-frontend enqueues the queries into a query-scheduler.&lt;/li&gt;
&lt;li&gt;The query-scheduler stores the queries in an in-memory queue where they wait for a querier to pick them up.&lt;/li&gt;
&lt;li&gt;Queriers pick up the queries, and executes them.&lt;/li&gt;
&lt;li&gt;The querier sends results back to query-frontend, which then forwards the results to the client.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;benefits-of-using-the-query-scheduler&#34;&gt;Benefits of using the query-scheduler&lt;/h2&gt;
&lt;p&gt;Query-scheduler enables the scaling of query-frontends. You might experience challenges when you scale query-frontend. To learn more about query-frontend scalability limits, refer to &lt;a href=&#34;../query-frontend/#why-query-frontend-scalability-is-limited&#34;&gt;Why query-frontend scalability is limited&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;how-query-scheduler-solves-query-frontend-scalability-limits&#34;&gt;How query-scheduler solves query-frontend scalability limits&lt;/h3&gt;
&lt;p&gt;When you use the query-scheduler, the queue is moved from the query-frontend to the query-scheduler, and the query-frontend can be scaled to any number of replicas.&lt;/p&gt;
&lt;p&gt;The query-scheduler is affected by the same scalability limits as the query-frontend, but because a query-scheduler replica can handle high amounts of query throughput, scaling the query-scheduler to a number of replicas greater than &lt;code&gt;-querier.max-concurrent&lt;/code&gt; is typically not required, even for very large Grafana Mimir clusters.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;To use the query-scheduler, query-frontends and queriers need to discover the addresses of query-scheduler instances.
The query-scheduler supports two service discovery mechanisms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DNS-based service discovery&lt;/li&gt;
&lt;li&gt;Ring-based service discovery&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;dns-based-service-discovery&#34;&gt;DNS-based service discovery&lt;/h3&gt;
&lt;p&gt;To use the query-scheduler with DNS-based service discovery, configure the query-frontends and queriers to connect to the query-scheduler:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query-frontend: &lt;code&gt;-query-frontend.scheduler-address&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Querier: &lt;code&gt;-querier.scheduler-address&lt;/code&gt;&lt;/li&gt;
&lt;/ul&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;The configured query-scheduler address should be in the &lt;code&gt;host:port&lt;/code&gt; format.&lt;/p&gt;
&lt;p&gt;If multiple query-schedulers are running, the host should be a DNS name resolving to all query-scheduler instances.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&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;The querier pulls queries only from the query-frontend or the query-scheduler, but not both.
&lt;code&gt;-querier.frontend-address&lt;/code&gt; and &lt;code&gt;-querier.scheduler-address&lt;/code&gt; options are mutually exclusive and you can only set one option.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;ring-based-service-discovery&#34;&gt;Ring-based service discovery&lt;/h3&gt;
&lt;p&gt;To use the query-scheduler with ring-based service discovery, configure the query-schedulers to join their hash ring, and the query-frontends and queriers to discover query-scheduler instances via the ring:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;Configure the hash ring&lt;/a&gt; for the query-scheduler.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;-query-scheduler.service-discovery-mode=ring&lt;/code&gt; (or its respective YAML configuration parameter) to query-scheduler, query-frontend and querier.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;-query-scheduler.ring.*&lt;/code&gt; flags (or their respective YAML configuration parameters) to query-scheduler, query-frontend and querier.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;migrate-from-dns-based-to-ring-based-service-discovery&#34;&gt;Migrate from DNS-based to ring-based service discovery&lt;/h4&gt;
&lt;p&gt;To migrate the query-scheduler from &lt;a href=&#34;#dns-based-service-discovery&#34;&gt;DNS-based service discovery&lt;/a&gt; to &lt;a href=&#34;#ring-based-service-discovery&#34;&gt;ring-based service discovery&lt;/a&gt;, perform the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Configure the &lt;strong&gt;query-scheduler&lt;/strong&gt; instances to join a ring:&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;-query-scheduler.service-discovery-mode=ring

# Configure the query-scheduler ring backend (e.g. &amp;#34;memberlist&amp;#34;).
-query-scheduler.ring.store=&amp;lt;backend&amp;gt;

# If the configured &amp;lt;backend&amp;gt; is &amp;#34;memberlist&amp;#34;, then ensure memberlist is configured for the query-scheduler.
-memberlist.join=&amp;lt;same as other Mimir components&amp;gt;

# If the configured &amp;lt;backend&amp;gt; is &amp;#34;consul&amp;#34; or &amp;#34;etcd&amp;#34;, then set their backend configuration
# for the query-scheduler ring:
# - Consul: -query-scheduler.ring.consul.*
# - Ecd:    -query-scheduler.ring.etcd.*&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wait until the query-scheduler instances have completed rolling out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensure the changes have been successfully applied; open the &lt;a href=&#34;../../../http-api/#query-scheduler-ring-status&#34;&gt;query-scheduler ring status&lt;/a&gt; page and ensure all query-scheduler instances are registered to the ring.
At this point, queriers and query-frontend are still discovering query-schedulers via DNS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure &lt;strong&gt;query-frontend&lt;/strong&gt; and &lt;strong&gt;querier&lt;/strong&gt; instances to discover query-schedulers via the ring:&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;-query-scheduler.service-discovery-mode=ring

# Remove the DNS-based service discovery configuration:
# -query-frontend.scheduler-address

# Configure the query-scheduler ring backend (e.g. &amp;#34;memberlist&amp;#34;).
-query-scheduler.ring.store=&amp;lt;backend&amp;gt;

# If the configured &amp;lt;backend&amp;gt; is &amp;#34;memberlist&amp;#34;, then ensure memberlist is configured for the query-scheduler.
-memberlist.join=&amp;lt;same as other Mimir components&amp;gt;

# If the configured &amp;lt;backend&amp;gt; is &amp;#34;consul&amp;#34; or &amp;#34;etcd&amp;#34;, then set their backend configuration
# for the query-scheduler ring:
# - Consul: -query-scheduler.ring.consul.*
# - Ecd:    -query-scheduler.ring.etcd.*&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&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;If you deploy your Mimir cluster with Jsonnet, refer to &lt;a href=&#34;../../../../set-up/jsonnet/migrate-query-scheduler-from-dns-to-ring-based-service-discovery/&#34;&gt;Migrate query-scheduler from DNS-based to ring-based service discovery&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;operational-considerations&#34;&gt;Operational considerations&lt;/h2&gt;
&lt;p&gt;For high-availability, run two query-scheduler replicas.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re running a Grafana Mimir cluster with a very high query throughput, you can add more query-scheduler replicas.
If you scale the query-scheduler, ensure that the number of replicas you add is less or equal than the configured &lt;code&gt;-querier.max-concurrent&lt;/code&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="optional-grafana-mimir-query-scheduler">(Optional) Grafana Mimir query-scheduler&lt;/h1>
&lt;p>The query-scheduler is an optional, stateless component that retains a queue of queries to execute, and distributes the workload to available &lt;a href="../querier/">queriers&lt;/a>.&lt;/p></description></item><item><title>(Optional) Grafana Mimir ruler</title><link>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/ruler/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.12.x/references/architecture/components/ruler/</guid><content><![CDATA[&lt;h1 id=&#34;optional-grafana-mimir-ruler&#34;&gt;(Optional) Grafana Mimir ruler&lt;/h1&gt;
&lt;p&gt;The ruler is an optional component that evaluates PromQL expressions defined in recording and alerting rules.
Each tenant has a set of recording and alerting rules and can group those rules into namespaces.&lt;/p&gt;
&lt;h2 id=&#34;operational-modes&#34;&gt;Operational modes&lt;/h2&gt;
&lt;p&gt;The ruler supports two different rule evaluation modes:&lt;/p&gt;
&lt;h3 id=&#34;internal&#34;&gt;Internal&lt;/h3&gt;
&lt;p&gt;This is the default mode. The ruler internally runs a querier and distributor, and evaluates recording and alerting rules in the ruler process itself.
To evaluate rules, the ruler connects directly to ingesters and store-gateways, and writes any resulting series to the ingesters.&lt;/p&gt;
&lt;p&gt;Configuration of the built-in querier and distributor uses their respective configuration parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../../../configure/configuration-parameters/#querier&#34;&gt;Querier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../../configure/configuration-parameters/#distributor&#34;&gt;Distributor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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;When you use the internal mode, the ruler uses no query acceleration techniques and the evaluation of very high cardinality queries could take longer than the evaluation interval, which may lead to missing data points in the evaluated recording rules.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;ruler-internal.svg&#34;
  alt=&#34;Architecture of Grafana Mimir&amp;rsquo;s ruler component in internal mode&#34;/&gt;&lt;/p&gt;
&lt;h3 id=&#34;remote&#34;&gt;Remote&lt;/h3&gt;
&lt;p&gt;In this mode the ruler delegates rules evaluation to the query-frontend. When enabled, the ruler leverages all the query acceleration techniques employed by the query-frontend, such as &lt;a href=&#34;../../query-sharding/&#34;&gt;query sharding&lt;/a&gt;.
To enable the remote operational mode, set the &lt;code&gt;-ruler.query-frontend.address&lt;/code&gt; CLI flag or its respective YAML configuration parameter for the ruler.
Communication between ruler and query-frontend is established over gRPC, so you can make use of client-side load balancing by prefixing the query-frontend address URL with &lt;code&gt;dns://&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;ruler-remote.svg&#34;
  alt=&#34;Architecture of Grafana Mimir&amp;rsquo;s ruler component in remote mode&#34;/&gt;&lt;/p&gt;
&lt;h2 id=&#34;recording-rules&#34;&gt;Recording rules&lt;/h2&gt;
&lt;p&gt;The ruler evaluates the expressions in the &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;recording rules&lt;/a&gt; at regular intervals and writes the results back to the ingesters.&lt;/p&gt;
&lt;h2 id=&#34;alerting-rules&#34;&gt;Alerting rules&lt;/h2&gt;
&lt;p&gt;The ruler evaluates the expressions in &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/#alerting-rules&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;alerting rules&lt;/a&gt; at regular intervals and if the result includes any series, the alert becomes active.
If an alerting rule has a defined &lt;code&gt;for&lt;/code&gt; duration, it enters the &lt;strong&gt;PENDING&lt;/strong&gt; (&lt;code&gt;pending&lt;/code&gt;) state.
After the alert has been active for the entire &lt;code&gt;for&lt;/code&gt; duration, it enters the &lt;strong&gt;FIRING&lt;/strong&gt; (&lt;code&gt;firing&lt;/code&gt;) state.
The ruler then notifies Alertmanagers of any &lt;strong&gt;FIRING&lt;/strong&gt; (&lt;code&gt;firing&lt;/code&gt;) alerts.&lt;/p&gt;
&lt;p&gt;Configure the addresses of Alertmanagers with the &lt;code&gt;-ruler.alertmanager-url&lt;/code&gt; flag. This flag supports the DNS service discovery format.
For more information about DNS service discovery, refer to &lt;a href=&#34;../../../../configure/about-dns-service-discovery/&#34;&gt;Supported discovery modes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using &lt;a href=&#34;../alertmanager/&#34;&gt;Mimir&amp;rsquo;s Alertmanager&lt;/a&gt;, point the address to Alertmanager&amp;rsquo;s API.
You can configure Alertmanager’s API prefix via the &lt;code&gt;-http.alertmanager-http-prefix&lt;/code&gt; flag, which defaults to &lt;code&gt;/alertmanager&lt;/code&gt;.
For example, if Alertmanager is listening at &lt;code&gt;http://mimir-alertmanager.namespace.svc.cluster.local&lt;/code&gt; and it is using the default API prefix, set &lt;code&gt;-ruler.alertmanager-url&lt;/code&gt; to &lt;code&gt;http://mimir-alertmanager.namespace.svc.cluster.local/alertmanager&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;federated-rule-groups&#34;&gt;Federated rule groups&lt;/h2&gt;
&lt;p&gt;A federated rule group is a rule group with a non-empty &lt;code&gt;source_tenants&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;source_tenants&lt;/code&gt; field allows aggregating data from multiple tenants while evaluating a rule group. The expressions
of each rule in the group will be evaluated against the data of all tenants in &lt;code&gt;source_tenants&lt;/code&gt;. If &lt;code&gt;source_tenants&lt;/code&gt; is
empty or omitted, then the tenant under which the group is created will be treated as the &lt;code&gt;source_tenant&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Below is an example of how a federated rule group would look like:&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: MyGroupName
source_tenants: [&amp;#34;tenant-a&amp;#34;, &amp;#34;tenant-b&amp;#34;]
rules:
  - record: sum:metric
    expr: sum(metric)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;In this example &lt;code&gt;MyGroupName&lt;/code&gt; rules will be evaluated against &lt;code&gt;tenant-a&lt;/code&gt; and &lt;code&gt;tenant-b&lt;/code&gt; tenants.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Federated rule groups are skipped during evaluation by default. This feature depends on
the cross-tenant query federation feature. To enable federated rules
set &lt;code&gt;-ruler.tenant-federation.enabled=true&lt;/code&gt; and &lt;code&gt;-tenant-federation.enabled=true&lt;/code&gt; CLI flags (or their respective YAML
config options).&lt;/p&gt;
&lt;p&gt;During evaluation query limits applied to single tenants are also applied to each query in the rule group. For example,
if &lt;code&gt;tenant-a&lt;/code&gt; has a federated rule group with &lt;code&gt;source_tenants: [tenant-b, tenant-c]&lt;/code&gt;, then query limits for &lt;code&gt;tenant-b&lt;/code&gt;
and &lt;code&gt;tenant-c&lt;/code&gt; will be applied. If any of these limits is exceeded, the whole evaluation will fail. No partial results
will be saved. The same &amp;ldquo;no partial results&amp;rdquo; guarantee applies to queries failing for other reasons (e.g. ingester
unavailability).&lt;/p&gt;
&lt;p&gt;The time series used during evaluation of federated rules will have the &lt;code&gt;__tenant_id__&lt;/code&gt; label, similar to how it is
present on series returned with cross-tenant query federation.&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;Federated rule groups allow data from multiple source tenants to be written into a single destination tenant.
This makes the separation of tenants&amp;rsquo; data less clear.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;tenant-a&lt;/code&gt; has a federated rule group that aggregates over &lt;code&gt;tenant-b&lt;/code&gt;&amp;rsquo;s data like &lt;code&gt;sum(metric_b)&lt;/code&gt; and writes the result back into &lt;code&gt;tenant-a&lt;/code&gt;&amp;rsquo;s storage as the metric &lt;code&gt;sum:metric_b&lt;/code&gt;.
Now &lt;code&gt;tenant-a&lt;/code&gt; contains some of &lt;code&gt;tenant-b&lt;/code&gt;&amp;rsquo;s data.&lt;/p&gt;
&lt;p&gt;Have this in mind when configuring the access control layer in front of Mimir and when enabling federated rules via &lt;code&gt;-ruler.tenant-federation.enabled&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;sharding&#34;&gt;Sharding&lt;/h2&gt;
&lt;p&gt;The ruler supports multi-tenancy and horizontal scalability.
To achieve horizontal scalability, the ruler shards the execution of rules by rule groups.
Ruler replicas form their own &lt;a href=&#34;../../hash-ring/&#34;&gt;hash ring&lt;/a&gt; stored in the &lt;a href=&#34;../../key-value-store/&#34;&gt;KV store&lt;/a&gt; to divide the work of the executing rules.&lt;/p&gt;
&lt;p&gt;To configure the rulers&amp;rsquo; hash ring, refer to &lt;a href=&#34;../../../../configure/configure-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;manage-alerting-and-recording-rules&#34;&gt;Manage alerting and recording rules&lt;/h2&gt;
&lt;p&gt;There is more than one way to manage alerting and recording rules.&lt;/p&gt;
&lt;h3 id=&#34;via-the-mimirtool-cli-tool&#34;&gt;Via the &lt;code&gt;mimirtool&lt;/code&gt; CLI tool&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;mimirtool rules&lt;/code&gt; command offers utility subcommands for linting, formatting, and uploading rules to Grafana Mimir.
For more information, refer to the &lt;a href=&#34;../../../../manage/tools/mimirtool/#rules&#34;&gt;&lt;code&gt;mimirtool rules&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;via-the-grafanamimiroperationsmimir-rules-action-github-action&#34;&gt;Via the &lt;code&gt;grafana/mimir/operations/mimir-rules-action&lt;/code&gt; GitHub Action&lt;/h3&gt;
&lt;p&gt;The GitHub Action &lt;code&gt;mimir-rules-action&lt;/code&gt; wraps some of the functionality of &lt;code&gt;mimirtool rules&lt;/code&gt;.
For more information, refer to the &lt;a href=&#34;https://github.com/grafana/mimir/blob/main/operations/mimir-rules-action/README.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;documentation of the action&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;via-the-http-configuration-api&#34;&gt;Via the HTTP configuration API&lt;/h3&gt;
&lt;p&gt;The ruler HTTP configuration API enables tenants to create, update, and delete rule groups.
For a complete list of endpoints and example requests, refer to &lt;a href=&#34;../../../http-api/#ruler&#34;&gt;ruler&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;state&#34;&gt;State&lt;/h2&gt;
&lt;p&gt;The ruler uses the backend configured via &lt;code&gt;-ruler-storage.backend&lt;/code&gt;.
The ruler supports the following backends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/s3&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Amazon S3&lt;/a&gt;: &lt;code&gt;-ruler-storage.backend=s3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Google Cloud Storage&lt;/a&gt;: &lt;code&gt;-ruler-storage.backend=gcs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://azure.microsoft.com/en-us/services/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Microsoft Azure Storage&lt;/a&gt;: &lt;code&gt;-ruler-storage.backend=azure&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.openstack.org/wiki/Swift&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenStack Swift&lt;/a&gt;: &lt;code&gt;-ruler-storage.backend=swift&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#local-storage&#34;&gt;Local storage&lt;/a&gt;: &lt;code&gt;-ruler-storage.backend=local&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;local-storage&#34;&gt;Local storage&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;local&lt;/code&gt; storage backend reads &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus recording rules&lt;/a&gt; from the local filesystem.&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;Local storage is a read-only backend that doesn&amp;rsquo;t support the creation and deletion of rules through the &lt;a href=&#34;#via-the-http-configuration-api&#34;&gt;Configuration API&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;When all rulers have the same rule files, local storage supports ruler sharding.
To facilitate sharding in Kubernetes, mount a &lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/configmap/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Kubernetes ConfigMap&lt;/a&gt; into every ruler pod.&lt;/p&gt;
&lt;p&gt;The following example shows a local storage definition:&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;-ruler-storage.backend=local
-ruler-storage.local.directory=/tmp/rules&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The ruler looks for tenant rules in the &lt;code&gt;/tmp/rules/&amp;lt;TENANT ID&amp;gt;&lt;/code&gt; directory.
The ruler requires rule files to be in the &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus format&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="optional-grafana-mimir-ruler">(Optional) Grafana Mimir ruler&lt;/h1>
&lt;p>The ruler is an optional component that evaluates PromQL expressions defined in recording and alerting rules.
Each tenant has a set of recording and alerting rules and can group those rules into namespaces.&lt;/p></description></item></channel></rss>