<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Grafana Mimir architecture on Grafana Labs</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/</link><description>Recent content in Grafana Mimir architecture on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/mimir/v2.2.x/operators-guide/architecture/index.xml" rel="self" type="application/rss+xml"/><item><title>About the Grafana Mimir architecture</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/about-grafana-mimir-architecture/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/about-grafana-mimir-architecture/</guid><content><![CDATA[&lt;h1 id=&#34;about-the-grafana-mimir-architecture&#34;&gt;About the Grafana Mimir architecture&lt;/h1&gt;
&lt;p&gt;Grafana Mimir has a microservices-based architecture.
The system has multiple horizontally scalable microservices that can run separately and in parallel.
Grafana Mimir microservices are called components.&lt;/p&gt;
&lt;p&gt;Grafana Mimir&amp;rsquo;s design compiles the code for all components into a single binary.
The &lt;code&gt;-target&lt;/code&gt; parameter controls which component(s) that single binary will behave as. For those looking for a simple way to get started, Grafana Mimir can also be run in &lt;a href=&#34;../deployment-modes/#monolithic-mode&#34;&gt;monolithic mode&lt;/a&gt;, with all components running simultaneously in one process.
For more information, refer to &lt;a href=&#34;../deployment-modes/&#34;&gt;Deployment modes&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;grafana-mimir-components&#34;&gt;Grafana Mimir components&lt;/h2&gt;
&lt;p&gt;Most components are stateless and do not require any data persisted between process restarts. Some components are stateful and rely on non-volatile storage to prevent data loss between process restarts. For details about each component, see its page in &lt;a href=&#34;../components/&#34;&gt;Components&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;the-write-path&#34;&gt;The write path&lt;/h3&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;write-path.svg&#34;
  alt=&#34;Architecture of Grafana Mimir&amp;rsquo;s write path&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Ingesters receive incoming samples from the distributors.
Each push request belongs to a tenant, and the ingester appends the received samples to the specific per-tenant TSDB that is stored on the local disk.
The samples that are received are both kept in-memory and written to a write-ahead log (WAL).
If the ingester abruptly terminates, the WAL can help to recover the in-memory series.
The per-tenant TSDB is lazily created in each ingester as soon as the first samples are received for that tenant.&lt;/p&gt;
&lt;p&gt;The in-memory samples are periodically flushed to disk, and the WAL is truncated, when a new TSDB block is created.
By default, this occurs every two hours.
Each newly created block is uploaded to long-term storage and kept in the ingester until the configured &lt;code&gt;-blocks-storage.tsdb.retention-period&lt;/code&gt; expires.
This gives &lt;a href=&#34;../components/querier/&#34;&gt;queriers&lt;/a&gt; and &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateways&lt;/a&gt; enough time to discover the new block on the storage and download its index-header.&lt;/p&gt;
&lt;p&gt;To effectively use the WAL, and to be able to recover the in-memory series if an ingester abruptly terminates, store the WAL to a persistent disk that can survive an ingester failure.
For example, when running in the cloud, include an AWS EBS volume or a GCP persistent disk.
If you are running the Grafana Mimir cluster in Kubernetes, you can use a StatefulSet with a persistent volume claim for the ingesters.
The location on the filesystem where the WAL is stored is the same location where local TSDB blocks (compacted from head) are stored. The location of the filesystem and the location of the local TSDB blocks cannot be decoupled.&lt;/p&gt;
&lt;p&gt;For more information, refer to &lt;a href=&#34;../../running-production-environment/production-tips/#how-to-estimate--querierquery-store-after&#34;&gt;timeline of block uploads&lt;/a&gt; and &lt;a href=&#34;../components/ingester/&#34;&gt;Ingester&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;series-sharding-and-replication&#34;&gt;Series sharding and replication&lt;/h4&gt;
&lt;p&gt;By default, each time series is replicated to three ingesters, and each ingester writes its own block to the long-term storage.
The &lt;a href=&#34;../components/compactor/&#34;&gt;Compactor&lt;/a&gt; merges blocks from multiple ingesters into a single block, and removes duplicate samples.
Blocks compaction significantly reduces storage utilization.
For more information, refer to &lt;a href=&#34;../components/compactor/&#34;&gt;Compactor&lt;/a&gt; and &lt;a href=&#34;../../running-production-environment/production-tips/&#34;&gt;Production tips&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;the-read-path&#34;&gt;The read path&lt;/h3&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;read-path.svg&#34;
  alt=&#34;Architecture of Grafana Mimir&amp;rsquo;s read path&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Queries coming into Grafana Mimir arrive at the &lt;a href=&#34;../components/query-frontend/&#34;&gt;query-frontend&lt;/a&gt;. The query-frontend then splits queries over longer time ranges into multiple, smaller queries.&lt;/p&gt;
&lt;p&gt;The query-frontend next checks the results cache. If the result of a query has been cached, the query-frontend returns the cached results. Queries that cannot be answered from the results cache are put into an in-memory queue within the query-frontend.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you run the optional &lt;a href=&#34;../components/query-scheduler/&#34;&gt;query-scheduler&lt;/a&gt; component, this queue is maintained in the query-scheduler instead of the query-frontend.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The queriers act as workers, pulling queries from the queue.&lt;/p&gt;
&lt;p&gt;The queriers connect to the store-gateways and the ingesters to fetch all the data needed to execute a query. For more information about how the query is executed, refer to &lt;a href=&#34;../components/querier/&#34;&gt;querier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After the querier executes the query, it returns the results to the query-frontend for aggregation. The query-frontend then returns the aggregated results to the client.&lt;/p&gt;
&lt;h2 id=&#34;the-role-of-prometheus&#34;&gt;The role of Prometheus&lt;/h2&gt;
&lt;p&gt;Prometheus instances scrape samples from various targets and push them to Grafana Mimir by using Prometheus’ &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/storage/#remote-storage-integrations&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;remote write API&lt;/a&gt;.
The remote write API emits batched &lt;a href=&#34;https://google.github.io/snappy/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Snappy&lt;/a&gt;-compressed &lt;a href=&#34;https://developers.google.com/protocol-buffers/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Protocol Buffer&lt;/a&gt; messages inside the body of an HTTP &lt;code&gt;PUT&lt;/code&gt; request.&lt;/p&gt;
&lt;p&gt;Mimir requires that each HTTP request has a header that specifies a tenant ID for the request. Request &lt;a href=&#34;../../securing/authentication-and-authorization/&#34;&gt;authentication and authorization&lt;/a&gt; are handled by an external reverse proxy.&lt;/p&gt;
&lt;p&gt;Incoming samples (writes from Prometheus) are handled by the &lt;a href=&#34;../components/distributor/&#34;&gt;distributor&lt;/a&gt;, and incoming reads (PromQL queries) are handled by the &lt;a href=&#34;../components/query-frontend/&#34;&gt;query frontend&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;long-term-storage&#34;&gt;Long-term storage&lt;/h2&gt;
&lt;p&gt;The Grafana Mimir storage format is based on &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus TSDB storage&lt;/a&gt;.
The Grafana Mimir storage format stores each tenant&amp;rsquo;s time series into their own TSDB, which persists series to an on-disk block.
By default, each block has a two-hour range.
Each on-disk block directory contains an index file, a file containing metadata, and the time series chunks.&lt;/p&gt;
&lt;p&gt;The TSDB block files contain samples for multiple series.
The series inside the blocks are indexed by a per-block index, which indexes both metric names and labels to time series in the block files.&lt;/p&gt;
&lt;p&gt;Grafana Mimir requires any of the following object stores for the block files:&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;/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;/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;/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;/li&gt;
&lt;li&gt;Local Filesystem (single node only)&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="about-the-grafana-mimir-architecture">About the Grafana Mimir architecture&lt;/h1>
&lt;p>Grafana Mimir has a microservices-based architecture.
The system has multiple horizontally scalable microservices that can run separately and in parallel.
Grafana Mimir microservices are called components.&lt;/p></description></item><item><title>Grafana Mimir deployment modes</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/deployment-modes/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/deployment-modes/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-deployment-modes&#34;&gt;Grafana Mimir deployment modes&lt;/h1&gt;
&lt;p&gt;You can deploy Grafana Mimir in one of two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monolithic mode&lt;/li&gt;
&lt;li&gt;Microservices mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The deployment mode is determined by the &lt;code&gt;-target&lt;/code&gt; parameter, which you can set via CLI flag or YAML configuration.&lt;/p&gt;
&lt;h2 id=&#34;monolithic-mode&#34;&gt;Monolithic mode&lt;/h2&gt;
&lt;p&gt;The monolithic mode runs all required components in a single process and is the default mode of operation, which you can set by specifying &lt;code&gt;-target=all&lt;/code&gt;. Monolithic mode is the simplest way to deploy Grafana Mimir and is useful if you want to get started quickly or want to work with Grafana Mimir in a development environment. To see the list of components that run when &lt;code&gt;-target&lt;/code&gt; is set to &lt;code&gt;all&lt;/code&gt;, run Grafana Mimir with the &lt;code&gt;-modules&lt;/code&gt; flag:&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;./mimir -modules&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;monolithic-mode.svg&#34;
  alt=&#34;Mimir&amp;rsquo;s monolithic mode&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Monolithic mode can be horizontally scaled out by deploying multiple Grafana Mimir binaries with &lt;code&gt;-target=all&lt;/code&gt;. This approach provides high-availability and increased scale without the configuration complexity of the full &lt;a href=&#34;#microservices-mode&#34;&gt;microservices deployment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;scaled-monolithic-mode.svg&#34;
  alt=&#34;Mimir&amp;rsquo;s horizontally scaled monolithic mode&#34;/&gt;&lt;/p&gt;
&lt;h2 id=&#34;microservices-mode&#34;&gt;Microservices mode&lt;/h2&gt;
&lt;p&gt;In microservices mode, components are deployed in distinct processes. Scaling is per component, which allows for greater flexibility in scaling and more granular failure domains. Microservices mode is the preferred method for a production deployment, but it is also the most complex.&lt;/p&gt;
&lt;p&gt;In microservices mode, each Grafana Mimir process is invoked with its &lt;code&gt;-target&lt;/code&gt; parameter set to a specific Grafana Mimir component (for example, &lt;code&gt;-target=ingester&lt;/code&gt; or &lt;code&gt;-target=distributor&lt;/code&gt;). To get a working Grafana Mimir instance, you must deploy every required component. For more information about each of the Grafana Mimir components, refer to &lt;a href=&#34;../&#34;&gt;Architecture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in deploying Grafana Mimir in microservices mode, we recommend that you use &lt;a href=&#34;https://kubernetes.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Kubernetes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;microservices-mode.svg&#34;
  alt=&#34;Mimir&amp;rsquo;s microservices mode&#34;/&gt;&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-deployment-modes">Grafana Mimir deployment modes&lt;/h1>
&lt;p>You can deploy Grafana Mimir in one of two modes:&lt;/p>
&lt;ul>
&lt;li>Monolithic mode&lt;/li>
&lt;li>Microservices mode&lt;/li>
&lt;/ul>
&lt;p>The deployment mode is determined by the &lt;code>-target&lt;/code> parameter, which you can set via CLI flag or YAML configuration.&lt;/p></description></item><item><title>Grafana Mimir components</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/components/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/components/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-components&#34;&gt;Grafana Mimir components&lt;/h1&gt;
&lt;p&gt;Grafana Mimir includes a set of components that interact to form a cluster.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/compactor/&#34;&gt;Compactor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/distributor/&#34;&gt;Distributor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/ingester/&#34;&gt;Ingester&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/querier/&#34;&gt;Querier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/query-frontend/&#34;&gt;Query-frontend&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/store-gateway/&#34;&gt;Store-gateway&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/alertmanager/&#34;&gt;(Optional) Alertmanager&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/overrides-exporter/&#34;&gt;(Optional) Overrides-exporter&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/query-scheduler/&#34;&gt;(Optional) Query-scheduler&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/mimir/v2.2.x/operators-guide/architecture/components/ruler/&#34;&gt;(Optional) Ruler&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
]]></content><description>&lt;h1 id="grafana-mimir-components">Grafana Mimir components&lt;/h1>
&lt;p>Grafana Mimir includes a set of components that interact to form a cluster.&lt;/p>
&lt;ul>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/compactor/">Compactor&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/distributor/">Distributor&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/ingester/">Ingester&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/querier/">Querier&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/query-frontend/">Query-frontend&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/store-gateway/">Store-gateway&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/alertmanager/">(Optional) Alertmanager&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/overrides-exporter/">(Optional) Overrides-exporter&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/query-scheduler/">(Optional) Query-scheduler&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/mimir/v2.2.x/operators-guide/architecture/components/ruler/">(Optional) Ruler&lt;/a>&lt;/li>&lt;/ul></description></item><item><title>Grafana Mimir binary index-header</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/binary-index-header/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/binary-index-header/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-binary-index-header&#34;&gt;Grafana Mimir binary index-header&lt;/h1&gt;
&lt;p&gt;To query series inside blocks from object storage, the &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateway&lt;/a&gt; must obtain information about each block index.
To obtain the required information, the store-gateway builds an index-header for each block and stores it on local disk.&lt;/p&gt;
&lt;p&gt;The store-gateway uses &lt;code&gt;GET byte range request&lt;/code&gt; to build the index-header, which contains specific sections of the block&amp;rsquo;s index. The store-gateway uses the index-header at query time.&lt;/p&gt;
&lt;p&gt;Because downloading specific sections of the original block&amp;rsquo;s index is a computationally easy operation, the index-header is not uploaded to the object storage.
If the index-header is not available on local disk, store-gateway instances (or the same instance after a rolling update completes without a persistent disk) re-build the index-header from the original block&amp;rsquo;s index.&lt;/p&gt;
&lt;h2 id=&#34;format-version-1&#34;&gt;Format (version 1)&lt;/h2&gt;
&lt;p&gt;The index-header is a subset of the block index and contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/prometheus/prometheus/blob/master/tsdb/docs/format/index.md#symbol-table&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Symbol Table&lt;/a&gt;: Used to unintern string values&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/prometheus/prometheus/blob/master/tsdb/docs/format/index.md#postings-offset-table&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Posting Offset Table&lt;/a&gt;: Used to look up postings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following example shows the format of the index-header file that is located in each block store-gateway local directory. It is terminated by a table of contents that serves as an entry point into the index.&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;┌─────────────────────────────┬───────────────────────────────┐
│    magic(0xBAAAD792) &amp;lt;4b&amp;gt;   │      version(1) &amp;lt;1 byte&amp;gt;      │
├─────────────────────────────┬───────────────────────────────┤
│  index version(2) &amp;lt;1 byte&amp;gt;  │ index PostingOffsetTable &amp;lt;8b&amp;gt; │
├─────────────────────────────┴───────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │      Symbol Table (exact copy from original index)      │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │      Posting Offset Table (exact copy from index)       │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │                          TOC                            │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="grafana-mimir-binary-index-header">Grafana Mimir binary index-header&lt;/h1>
&lt;p>To query series inside blocks from object storage, the &lt;a href="../components/store-gateway/">store-gateway&lt;/a> must obtain information about each block index.
To obtain the required information, the store-gateway builds an index-header for each block and stores it on local disk.&lt;/p></description></item><item><title>Grafana Mimir bucket index</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/bucket-index/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/bucket-index/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-bucket-index&#34;&gt;Grafana Mimir bucket index&lt;/h1&gt;
&lt;p&gt;The bucket index is a per-tenant file that contains the list of blocks and block deletion marks in the storage. The bucket index is stored in the backend object storage, is periodically updated by the compactor, and used by queriers, store-gateways, and rulers (in &lt;a href=&#34;../components/ruler/#internal&#34;&gt;internal&lt;/a&gt; operational mode) to discover blocks in the storage.&lt;/p&gt;
&lt;p&gt;The bucket index is enabled by default, but is optional. It can be disabled via &lt;code&gt;-blocks-storage.bucket-store.bucket-index.enabled=false&lt;/code&gt; (or its respective YAML configuration option).
Disabling the bucket index is not recommended.&lt;/p&gt;
&lt;h2 id=&#34;benefits&#34;&gt;Benefits&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/querier/&#34;&gt;querier&lt;/a&gt;, &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateway&lt;/a&gt; and &lt;a href=&#34;../components/ruler/&#34;&gt;ruler&lt;/a&gt; must have an almost up-to-date view of the storage bucket, in order to find the right blocks to lookup at query time (querier) and load block&amp;rsquo;s &lt;a href=&#34;../binary-index-header/&#34;&gt;index-header&lt;/a&gt; (store-gateway).
Because of this, they need to periodically scan the bucket to look for new blocks uploaded by ingester or compactor, and blocks deleted (or marked for deletion) by compactor.&lt;/p&gt;
&lt;p&gt;When the bucket index is enabled, the querier, store-gateway, and ruler periodically look up the per-tenant bucket index instead of scanning the bucket via &lt;code&gt;list objects&lt;/code&gt; operations.&lt;/p&gt;
&lt;p&gt;This provides the following benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reduced number of API calls to the object storage by querier and store-gateway&lt;/li&gt;
&lt;li&gt;No &amp;ldquo;list objects&amp;rdquo; storage API calls performed by querier and store-gateway&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;../components/querier/&#34;&gt;querier&lt;/a&gt; is up and running immediately after the startup, so there is no need to run an initial bucket scan&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;structure-of-the-index&#34;&gt;Structure of the index&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;bucket-index.json.gz&lt;/code&gt; contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;blocks&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
List of complete blocks of a tenant, including blocks marked for deletion. Partial blocks are excluded from the index.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;block_deletion_marks&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
List of block deletion marks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;updated_at&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
A Unix timestamp, with precision measured in seconds, displays the last time index was updated and written to the storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-it-gets-updated&#34;&gt;How it gets updated&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/compactor/&#34;&gt;compactor&lt;/a&gt; periodically scans the bucket and uploads an updated bucket index to the storage.
You can configure the frequency with which the bucket index is updated via &lt;code&gt;-compactor.cleanup-interval&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The use of the bucket index is optional, but the index is built and updated by the compactor even if &lt;code&gt;-blocks-storage.bucket-store.bucket-index.enabled=false&lt;/code&gt;.
This behavior ensures that the bucket index for any tenant exists and that query result consistency is guaranteed if a Grafana Mimir cluster operator enable the bucket index in a live cluster.
The overhead introduced by keeping the bucket index updated is not signifcant.&lt;/p&gt;
&lt;h2 id=&#34;how-its-used-by-the-querier&#34;&gt;How it&amp;rsquo;s used by the querier&lt;/h2&gt;
&lt;p&gt;At query time the &lt;a href=&#34;../components/querier/&#34;&gt;querier&lt;/a&gt; and &lt;a href=&#34;../components/ruler/&#34;&gt;ruler&lt;/a&gt; determine whether the bucket index for the tenant has already been loaded to memory.
If not, the querier and ruler download it from the storage and cache it.&lt;/p&gt;
&lt;p&gt;Because the bucket index is a small file, lazy downloading it doesn&amp;rsquo;t have a significant impact on first query performances, but it does allow a querier to get up and running without pre-downloading every tenant&amp;rsquo;s bucket index.
In addition, if the &lt;a href=&#34;../components/querier/#metadata-cache&#34;&gt;metadata cache&lt;/a&gt; is enabled, the bucket index is cached for a short time in a shared cache, which reduces the latency and number of API calls to the object storage in case multiple queriers and rulers fetch the same tenant&amp;rsquo;s bucket index within a short time.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;bucket-index-querier-workflow.png&#34;
  alt=&#34;Querier - Bucket index&#34;/&gt;&lt;/p&gt;
&lt;!-- Diagram source at https://docs.google.com/presentation/d/1bHp8_zcoWCYoNU2AhO2lSagQyuIrghkCncViSqn14cU/edit --&gt;
&lt;p&gt;While in-memory, a background process keeps the bucket index updated periodically so that subsequent queries from the same tenant to the same querier instance uses the cached (and periodically updated) bucket index.&lt;/p&gt;
&lt;p&gt;The following configuration options determine bucket index update intervals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-blocks-storage.bucket-store.sync-interval&lt;/code&gt;&lt;br /&gt;
This option configures how frequently a cached bucket index is refreshed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-blocks-storage.bucket-store.bucket-index.update-on-error-interval&lt;/code&gt;&lt;br /&gt;
If downloading a bucket index fails, the failure is cached for a short time so that the backend storage doesn&amp;rsquo;t experience a large volume of storage requests.
This option configures the frequency with which the bucket store attempts to load a failed bucket index.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a bucket index is unused for the amount of time configured via &lt;code&gt;-blocks-storage.bucket-store.bucket-index.idle-timeout&lt;/code&gt;, (for example, if a querier instance is not receiving any query from the tenant), the querier offload its, which stops the querier from updating it at regular intervals.
This is useful for tenants that are resharded to different queriers when &lt;a href=&#34;../../configuring/configuring-shuffle-sharding/&#34;&gt;shuffle sharding&lt;/a&gt; is enabled.&lt;/p&gt;
&lt;p&gt;At query time the querier and ruler determine how old a bucket index is based on its &lt;code&gt;updated_at&lt;/code&gt;.
If the age is older than the period configured via &lt;code&gt;-blocks-storage.bucket-store.bucket-index.max-stale-period&lt;/code&gt; a query fails.
This circuit breaker ensures queriers and rulers do not return any partial query results due to a stale view over the long-term storage.&lt;/p&gt;
&lt;h2 id=&#34;how-its-used-by-the-store-gateway&#34;&gt;How it&amp;rsquo;s used by the store-gateway&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateway&lt;/a&gt;, at startup and periodically, fetches the bucket index for each tenant that belong to their shard, and uses it as the source of truth for the blocks and deletion marks in the storage. This removes the need to periodically scan the bucket to discover blocks belonging to their shard.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-bucket-index">Grafana Mimir bucket index&lt;/h1>
&lt;p>The bucket index is a per-tenant file that contains the list of blocks and block deletion marks in the storage. The bucket index is stored in the backend object storage, is periodically updated by the compactor, and used by queriers, store-gateways, and rulers (in &lt;a href="../components/ruler/#internal">internal&lt;/a> operational mode) to discover blocks in the storage.&lt;/p></description></item><item><title>Grafana Mimir hash rings</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/hash-ring/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/hash-ring/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-hash-rings&#34;&gt;Grafana Mimir hash rings&lt;/h1&gt;
&lt;p&gt;Hash rings are a distributed &lt;a href=&#34;https://en.wikipedia.org/wiki/Consistent_hashing&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;consistent hashing scheme&lt;/a&gt; and are widely used by Grafana Mimir for sharding and replication.&lt;/p&gt;
&lt;h2 id=&#34;how-the-hash-ring-works-in-grafana-mimir&#34;&gt;How the hash ring works in Grafana Mimir&lt;/h2&gt;
&lt;p&gt;The hash ring in Grafana Mimir is used to share work across several replicas of a component in a consistent way, so that any other component can decide which address to talk to.
The workload or data to share is hashed first and the result of the hashing is used to find which ring member owns it.&lt;/p&gt;
&lt;p&gt;Grafana Mimir uses the &lt;code&gt;fnv32a&lt;/code&gt; hash function, which returns 32-bit unsigned integers so its value can be between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;(2^32)-1&lt;/code&gt;, inclusive.
This value is called &lt;em&gt;token&lt;/em&gt; and used as the ID of the data.
The token determines the location on the hash ring deterministically.
This allows independent determination of what instance of Grafana Mimir is the authoritative owner of any specific data.&lt;/p&gt;
&lt;p&gt;For example, series are sharded across &lt;a href=&#34;../components/ingester/&#34;&gt;ingesters&lt;/a&gt;.
The token of a given series is computed by hashing all of the series’ labels and the tenant ID: the result of which is an unsigned 32-bit integer within the space of the tokens.
The ingester that owns that series is the instance that owns the range of the tokens, including the series&amp;rsquo; token.&lt;/p&gt;
&lt;p&gt;To divide up set of possible tokens (&lt;code&gt;2^32&lt;/code&gt;) across the available instances within the cluster, all of the running instances of a given Grafana Mimir component, such as the ingesters, join a hash ring.
The hash ring is a data structure that splits the space of the tokens into multiple ranges, and assigns each range to a given Grafana Mimir ring member.&lt;/p&gt;
&lt;p&gt;Upon startup, an instance generates random token values, and it registers them into the ring.
The values that each instance registers determine which instance owns a given token.
A token is owned by the instance that registered the smallest value that is higher than the token being looked up (by wrapping around zero when it reaches &lt;code&gt;(2^32)-1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To replicate the data across multiple instances, Grafana Mimir finds the replicas by starting from the authoritative owner of the data and walking the ring clockwise.
Data is replicated to the next instances found while walking the ring.&lt;/p&gt;
&lt;h3 id=&#34;a-practical-example&#34;&gt;A practical example&lt;/h3&gt;
&lt;p&gt;To better understand how it works, take four ingesters and a tokens space between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;9&lt;/code&gt; as an example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ingester #1 is registered in the ring with the token &lt;code&gt;2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #2 is registered in the ring with the token &lt;code&gt;4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #3 is registered in the ring with the token &lt;code&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #4 is registered in the ring with the token &lt;code&gt;9&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grafana Mimir receives an incoming sample for the series &lt;code&gt;{__name__=&amp;quot;cpu_seconds_total&amp;quot;,instance=&amp;quot;1.1.1.1&amp;quot;}&lt;/code&gt;.
It hashes the series’ labels, and the result of the hashing function is the token &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To find which ingester owns token &lt;code&gt;3&lt;/code&gt;, Grafana Mimir looks up the token &lt;code&gt;3&lt;/code&gt; in the ring and finds the ingester that is registered with the smallest token larger than &lt;code&gt;3&lt;/code&gt;.
The ingester #2, which is registered with token &lt;code&gt;4&lt;/code&gt;, is the authoritative owner of the series &lt;code&gt;{__name__=&amp;quot;cpu_seconds_total&amp;quot;,instance=&amp;quot;1.1.1.1&amp;quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;hash-ring-without-replication.png&#34;
  alt=&#34;Hash ring without replication&#34;/&gt;&lt;/p&gt;
&lt;p&gt;By default, Grafana Mimir replicates each series to three ingesters.
After finding the authoritative owner of the series, Grafana Mimir continues to walk the ring clockwise to find the remaining two instances where the series should be replicated.
In the example that follows, the series are replicated to the instances of &lt;code&gt;Ingester #3&lt;/code&gt; and &lt;code&gt;Ingester #4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;hash-ring-with-replication.png&#34;
  alt=&#34;Hash ring with replication&#34;/&gt;&lt;/p&gt;
&lt;h3 id=&#34;consistent-hashing&#34;&gt;Consistent hashing&lt;/h3&gt;
&lt;p&gt;The hash ring guarantees the property known as consistent hashing.&lt;/p&gt;
&lt;p&gt;When an instance is added or removed from the ring, consistent hashing minimizes the number of tokens that are moved from one instance to another.
On average, the number of tokens that need to move to a different instance is only &lt;code&gt;n/m&lt;/code&gt;, where &lt;code&gt;n&lt;/code&gt; is the total number of tokens (32-bit unsigned integer) and &lt;code&gt;m&lt;/code&gt; is the number of instances that are registered in the ring.&lt;/p&gt;
&lt;h2 id=&#34;components-that-use-the-hash-ring&#34;&gt;Components that use the hash ring&lt;/h2&gt;
&lt;p&gt;There are several Grafana Mimir components that need a hash ring.
Each of the following components builds an independent hash ring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../components/ingester/&#34;&gt;Ingesters&lt;/a&gt; shard and replicate series.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/distributor/&#34;&gt;Distributors&lt;/a&gt; enforce rate limits.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/compactor/&#34;&gt;Compactors&lt;/a&gt; shard compaction workload.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/store-gateway/&#34;&gt;Store-gateways&lt;/a&gt; shard blocks to query from long-term storage.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/ruler/&#34;&gt;(Optional) Rulers&lt;/a&gt; shard rule groups to evaluate.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/alertmanager/&#34;&gt;(Optional) Alertmanagers&lt;/a&gt; shard tenants.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-the-hash-ring-is-shared-between-grafana-mimir-instances&#34;&gt;How the hash ring is shared between Grafana Mimir instances&lt;/h2&gt;
&lt;p&gt;Hash ring data structures need to be shared between Grafana Mimir instances.
To propagate changes to the hash ring, Grafana Mimir uses a key-value store.
The key-value store is required and can be configured independently for the hash rings of different components.&lt;/p&gt;
&lt;p&gt;For more information, see the &lt;a href=&#34;../key-value-store/&#34;&gt;key-value store documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;features-that-are-built-using-the-hash-ring&#34;&gt;Features that are built using the hash ring&lt;/h2&gt;
&lt;p&gt;Grafana Mimir primarily uses the hash ring for sharding and replication.
Features that are built using the hash ring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Service discovery&lt;/strong&gt;: Instances can discover each other looking up who is registered in the ring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heartbeating&lt;/strong&gt;: Instances periodically send an heartbeat to the ring to signal they&amp;rsquo;re up and running. An instance is considered unhealthy if misses the heartbeat for some period of time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zone-aware replication&lt;/strong&gt;: Zone-aware replication is the replication of data across failure domains and can be optionally enabled in Grafana Mimir. For more information, see &lt;a href=&#34;../../configuring/configuring-zone-aware-replication/&#34;&gt;configuring zone-aware replication&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shuffle sharding&lt;/strong&gt;: Grafana Mimir optionally supports shuffle sharding in a multi-tenant cluster, to reduce the blast radius of an outage and better isolate tenants. For more information, refer to &lt;a href=&#34;../../configuring/configuring-shuffle-sharding/&#34;&gt;configure shuffle sharding&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="grafana-mimir-hash-rings">Grafana Mimir hash rings&lt;/h1>
&lt;p>Hash rings are a distributed &lt;a href="https://en.wikipedia.org/wiki/Consistent_hashing" target="_blank" rel="noopener noreferrer">consistent hashing scheme&lt;/a> and are widely used by Grafana Mimir for sharding and replication.&lt;/p>
&lt;h2 id="how-the-hash-ring-works-in-grafana-mimir">How the hash ring works in Grafana Mimir&lt;/h2>
&lt;p>The hash ring in Grafana Mimir is used to share work across several replicas of a component in a consistent way, so that any other component can decide which address to talk to.
The workload or data to share is hashed first and the result of the hashing is used to find which ring member owns it.&lt;/p></description></item><item><title>Grafana Mimir key-value store</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/key-value-store/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/key-value-store/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-key-value-store&#34;&gt;Grafana Mimir key-value store&lt;/h1&gt;
&lt;p&gt;A key-value (KV) store is a database that stores data indexed by key.
Grafana Mimir requires a key-value store for the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../hash-ring/&#34;&gt;Hash ring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../configuring/configuring-high-availability-deduplication/&#34;&gt;(Optional) Distributor high-availability tracker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;supported-key-value-store-backends&#34;&gt;Supported key-value store backends&lt;/h2&gt;
&lt;p&gt;Grafana Mimir supports the following key-value (KV) store backends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gossip-based &lt;a href=&#34;https://github.com/hashicorp/memberlist&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;memberlist&lt;/a&gt; protocol (default)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.consul.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consul&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://etcd.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Etcd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;gossip-based-memberlist-protocol-default&#34;&gt;Gossip-based memberlist protocol (default)&lt;/h3&gt;
&lt;p&gt;By default, Grafana Mimir instances use a Gossip-based protocol to join a memberlist cluster.
The data is shared between the instances using peer-to-peer communication and no external dependency is required.&lt;/p&gt;
&lt;p&gt;We recommend that you use memberlist to run Grafana Mimir.&lt;/p&gt;
&lt;p&gt;To configure memberlist, refer to &lt;a href=&#34;../../configuring/configuring-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;consul&#34;&gt;Consul&lt;/h3&gt;
&lt;p&gt;Grafana Mimir supports &lt;a href=&#34;https://www.consul.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consul&lt;/a&gt; as a backend KV store.
If you want to use Consul, you must install it. The Grafana Mimir installation does not include Consul.&lt;/p&gt;
&lt;p&gt;To configure Consul, refer to &lt;a href=&#34;../../configuring/configuring-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;etcd&#34;&gt;Etcd&lt;/h3&gt;
&lt;p&gt;Grafana Mimir supports &lt;a href=&#34;https://etcd.io&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;etcd&lt;/a&gt; as a backend KV store.
If you want to use etcd, you must install it. The Grafana Mimir installation does not include etcd.&lt;/p&gt;
&lt;p&gt;To configure etcd, refer to &lt;a href=&#34;../../configuring/configuring-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-key-value-store">Grafana Mimir key-value store&lt;/h1>
&lt;p>A key-value (KV) store is a database that stores data indexed by key.
Grafana Mimir requires a key-value store for the following features:&lt;/p></description></item><item><title>Grafana Mimir memberlist and gossip protocol</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/memberlist-and-the-gossip-protocol/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/memberlist-and-the-gossip-protocol/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-memberlist-and-gossip-protocol&#34;&gt;Grafana Mimir memberlist and gossip protocol&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/hashicorp/memberlist&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Memberlist&lt;/a&gt; is a Go library that manages cluster membership, node failure detection, and message passing using a gossip-based protocol.
Memberlist is eventually consistent and network partitions are partially tolerated by attempting to communicate to potentially dead nodes through multiple routes.&lt;/p&gt;
&lt;p&gt;By default, Grafana Mimir uses memberlist to implement a &lt;a href=&#34;../key-value-store/&#34;&gt;key-value (KV) store&lt;/a&gt; to share the &lt;a href=&#34;../hash-ring/&#34;&gt;hash ring&lt;/a&gt; data structures between instances.&lt;/p&gt;
&lt;p&gt;When using a memberlist-based KV store, each instance maintains a copy of the hash rings.
Each Mimir instance updates a hash ring locally and uses memberlist to propagate the changes to other instances.
Updates generated locally and updates received from other instances are merged together to form the current state of the ring on the instance.&lt;/p&gt;
&lt;p&gt;To configure memberlist, refer to &lt;a href=&#34;../../configuring/configuring-hash-rings/&#34;&gt;configuring hash rings&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-memberlist-propagates-hash-ring-changes&#34;&gt;How memberlist propagates hash ring changes&lt;/h2&gt;
&lt;p&gt;When using a memberlist-based KV store, every Grafana Mimir instance propagates the hash ring data structures to other instances using the following techniques:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Propagating only the differences introduced in recent changes.&lt;/li&gt;
&lt;li&gt;Propagating the full hash ring data structure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every &lt;code&gt;-memberlist.gossip-interval&lt;/code&gt; an instance randomly selects a subset of all Grafana Mimir cluster instances configured by &lt;code&gt;-memberlist.gossip-nodes&lt;/code&gt; and sends the latest changes to the selected instances.
This operation is performed frequently and it&amp;rsquo;s the primary technique used to propagate changes.&lt;/p&gt;
&lt;p&gt;In addition, every &lt;code&gt;-memberlist.pullpush-interval&lt;/code&gt; an instance randomly selects another instance in the Grafana Mimir cluster and transfers the full content of the KV store, including all hash rings (unless &lt;code&gt;-memberlist.pullpush-interval&lt;/code&gt; is zero, which disables this behavior).
After this operation is complete, the two instances have the same content as the KV store.
This operation is computationally more expensive, and as a result, it&amp;rsquo;s performed less frequently. The operation ensures that the hash rings periodically reconcile to a common state.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-memberlist-and-gossip-protocol">Grafana Mimir memberlist and gossip protocol&lt;/h1>
&lt;p>&lt;a href="https://github.com/hashicorp/memberlist" target="_blank" rel="noopener noreferrer">Memberlist&lt;/a> is a Go library that manages cluster membership, node failure detection, and message passing using a gossip-based protocol.
Memberlist is eventually consistent and network partitions are partially tolerated by attempting to communicate to potentially dead nodes through multiple routes.&lt;/p></description></item><item><title>Grafana Mimir query sharding</title><link>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/query-sharding/</link><pubDate>Sat, 11 Apr 2026 21:28:04 +0000</pubDate><guid>https://grafana.com/docs/mimir/v2.2.x/operators-guide/architecture/query-sharding/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-mimir-query-sharding&#34;&gt;Grafana Mimir query sharding&lt;/h1&gt;
&lt;p&gt;Mimir includes the ability to run a single query across multiple machines. This is
achieved by breaking the dataset into smaller pieces. These smaller pieces are
called shards. Each shard then gets queried in a partial query, and those
partial queries are distributed by the query-frontend to run on different
queriers in parallel. The results of those partial queries are aggregated by the
query-frontend to return the full query result.&lt;/p&gt;
&lt;h2 id=&#34;query-sharding-at-glance&#34;&gt;Query sharding at glance&lt;/h2&gt;
&lt;p&gt;Not all queries are shardable. While the full query is not shardable, the inner
parts of a query could still be shardable.&lt;/p&gt;
&lt;p&gt;In particular associative aggregations (like &lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;count&lt;/code&gt;,
&lt;code&gt;avg&lt;/code&gt;) are shardable, while some query functions (like &lt;code&gt;absent&lt;/code&gt;, &lt;code&gt;absent_over_time&lt;/code&gt;,
&lt;code&gt;histogram_quantile&lt;/code&gt;, &lt;code&gt;sort_desc&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;) are not.&lt;/p&gt;
&lt;p&gt;In the following examples we look at a concrete example with a shard count of
&lt;code&gt;3&lt;/code&gt;. All the partial queries that include a label selector &lt;code&gt;__query_shard__&lt;/code&gt;
are executed in parallel. The &lt;code&gt;concat()&lt;/code&gt; annotation is used to show when partial
query results are concatenated/merged by the query-frontend.&lt;/p&gt;
&lt;h3 id=&#34;example-1-full-query-is-shardable&#34;&gt;Example 1: Full query is shardable&lt;/h3&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;promql&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-promql&#34;&gt;sum(rate(metric[1m]))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Is executed as (assuming a shard count of 3):&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;promql&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-promql&#34;&gt;sum(
  concat(
    sum(rate(metric{__query_shard__=&amp;#34;1_of_3&amp;#34;}[1m]))
    sum(rate(metric{__query_shard__=&amp;#34;2_of_3&amp;#34;}[1m]))
    sum(rate(metric{__query_shard__=&amp;#34;3_of_3&amp;#34;}[1m]))
  )
)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;example-2-inner-part-is-shardable&#34;&gt;Example 2: Inner part is shardable&lt;/h3&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;promql&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-promql&#34;&gt;histogram_quantile(0.99, sum by(le) (rate(metric[1m])))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Is executed as (assuming a shard count of 3):&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;promql&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-promql&#34;&gt;histogram_quantile(0.99, sum by(le) (
  concat(
    sum by(le) (rate(metric{__query_shard__=&amp;#34;1_of_3&amp;#34;}[1m]))
    sum by(le) (rate(metric{__query_shard__=&amp;#34;2_of_3&amp;#34;}[1m]))
    sum by(le) (rate(metric{__query_shard__=&amp;#34;3_of_3&amp;#34;}[1m]))
  )
))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;example-3-query-with-two-shardable-portions&#34;&gt;Example 3: Query with two shardable portions&lt;/h3&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;promql&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-promql&#34;&gt;sum(rate(failed[1m])) / sum(rate(total[1m]))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Is executed as (assuming a shard count of 3):&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;promql&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-promql&#34;&gt;sum(
  concat(
    sum (rate(failed{__query_shard__=&amp;#34;1_of_3&amp;#34;}[1m]))
    sum (rate(failed{__query_shard__=&amp;#34;2_of_3&amp;#34;}[1m]))
    sum (rate(failed{__query_shard__=&amp;#34;3_of_3&amp;#34;}[1m]))
  )
)
/
sum(
  concat(
    sum (rate(total{__query_shard__=&amp;#34;1_of_3&amp;#34;}[1m]))
    sum (rate(total{__query_shard__=&amp;#34;2_of_3&amp;#34;}[1m]))
    sum (rate(total{__query_shard__=&amp;#34;3_of_3&amp;#34;}[1m]))
  )
)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;query-sharding.png&#34;
  alt=&#34;Flow of a query with two shardable portions&#34;/&gt;&lt;/p&gt;
&lt;h2 id=&#34;how-to-enable-query-sharding&#34;&gt;How to enable query sharding&lt;/h2&gt;
&lt;p&gt;In order to enable query sharding you need to opt-in by setting
&lt;code&gt;-query-frontend.parallelize-shardable-queries&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each shardable portion of a query is split into
&lt;code&gt;-query-frontend.query-sharding-total-shards&lt;/code&gt; partial queries. If a query has multiple
inner portions that can be sharded, each portion is sharded
&lt;code&gt;-query-frontend.query-sharding-total-shards&lt;/code&gt; times. In some cases, this could lead to
an explosion of queries. For this reason, there is a parameter that allows to
modify the default hard limit of 128 queries on the total number of partial
queries a single input query can generate:
&lt;code&gt;-query-frontend.query-sharding-max-sharded-queries&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When running a query over a large time range and
&lt;code&gt;-query-frontend.split-queries-by-interval&lt;/code&gt; is enabled, the
&lt;code&gt;-query-frontend.query-sharding-max-sharded-queries&lt;/code&gt; limit applies on the total
number of queries which have been split by time (first) and by shards (second).&lt;/p&gt;
&lt;p&gt;As an example, if &lt;code&gt;-query-frontend.query-sharding-max-sharded-queries=128&lt;/code&gt; and
&lt;code&gt;-query-frontend.split-queries-by-interval=24h&lt;/code&gt;, and you run a query over 8 days, each
daily query will have a max of 128 / 8 days = 16 partial queries per day.&lt;/p&gt;
&lt;p&gt;After enabling query sharding in a microservices deployment, the query
frontends will start processing the aggregation of the partial queries. Hence
it is important to configure some PromQL engine specific parameters on the
query-frontend too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-querier.max-concurrent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-querier.timeout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-querier.max-samples&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-querier.default-evaluation-interval&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-querier.lookback-delta&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;operational-considerations&#34;&gt;Operational considerations&lt;/h2&gt;
&lt;p&gt;Splitting a single query into sharded queries increases the quantity of queries
that must be processed. Parallelization decreases the query processing time,
but increases the load on querier components and their underlying data stores
(ingesters for recent data and store-gateway for historic data). The
caching layer for chunks and indexes will also experience an increased load.&lt;/p&gt;
&lt;p&gt;We also recommend to increase the maximum number of queries scheduled in
parallel by the query-frontend, multiplying the previously set value of
&lt;code&gt;-querier.max-query-parallelism&lt;/code&gt; by
&lt;code&gt;-query-frontend.query-sharding-total-shards&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;verification&#34;&gt;Verification&lt;/h2&gt;
&lt;h3 id=&#34;query-statistics&#34;&gt;Query statistics&lt;/h3&gt;
&lt;p&gt;The query statistics logged by the query-frontend allow to check if query sharding was
used for an individual query. The field &lt;code&gt;sharded_queries&lt;/code&gt; contains the amount
of parallelly executed partial queries.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;sharded_queries&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, either the query is not shardable or query
sharding is disabled for cluster or tenant. This is a log line of an
unshardable query:&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;sharded_queries=0  param_query=&amp;#34;absent(up{job=\&amp;#34;my-service\&amp;#34;})&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When &lt;code&gt;sharded_queries&lt;/code&gt; matches the configured shard count, query sharding is
operational and the query has only a single leg (assuming time splitting is
disabled or the query doesn&amp;rsquo;t span across multiple days). The following log
line represents that case with a shard count of &lt;code&gt;16&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;sharded_queries=16 query=&amp;#34;sum(rate(prometheus_engine_queries[5m]))&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When &lt;code&gt;sharded_queries&lt;/code&gt; is a multiple of the configured shard count, query
sharding is operational and the query has multiple legs (assuming time
splitting is disabled or the query doesn&amp;rsquo;t span across multiple days). The
following log line shows a query with two legs and with a configured shard
count of &lt;code&gt;16&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;sharded_queries=32 query=&amp;#34;sum(rate(prometheus_engine_queries{engine=\&amp;#34;ruler\&amp;#34;}[5m]))/sum(rate(prometheus_engine_queries[5m]))&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The query-frontend also exposes metrics, which can be useful to understand the
query workload&amp;rsquo;s parallelism as a whole.&lt;/p&gt;
&lt;p&gt;You can run the following query to get the ratio of queries which have been successfully sharded:&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;promql&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-promql&#34;&gt;sum(rate(cortex_frontend_query_sharding_rewrites_succeeded_total[$__rate_interval])) /
sum(rate(cortex_frontend_query_sharding_rewrites_attempted_total[$__rate_interval]))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The histogram &lt;code&gt;cortex_frontend_sharded_queries_per_query&lt;/code&gt; allows to understand
how many sharded sub queries are generated per query.&lt;/p&gt;
]]></content><description>&lt;h1 id="grafana-mimir-query-sharding">Grafana Mimir query sharding&lt;/h1>
&lt;p>Mimir includes the ability to run a single query across multiple machines. This is
achieved by breaking the dataset into smaller pieces. These smaller pieces are
called shards. Each shard then gets queried in a partial query, and those
partial queries are distributed by the query-frontend to run on different
queriers in parallel. The results of those partial queries are aggregated by the
query-frontend to return the full query result.&lt;/p></description></item></channel></rss>