<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Migrate to Grafana Mimir on Grafana Labs</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/</link><description>Recent content in Migrate to Grafana Mimir on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/mimir/v3.1.x/set-up/migrate/index.xml" rel="self" type="application/rss+xml"/><item><title>Migrate from Cortex to Grafana Mimir</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-cortex/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-cortex/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-from-cortex-to-grafana-mimir&#34;&gt;Migrate from Cortex to Grafana Mimir&lt;/h1&gt;
&lt;p&gt;As an operator, you can migrate a Jsonnet deployment of &lt;a href=&#34;https://cortexmetrics.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Cortex&lt;/a&gt; to Grafana Mimir.
The overview includes the steps required for any environment. To migrate deployment environments with Jsonnet, see &lt;a href=&#34;#migrate-to-grafana-mimir-using-jsonnet&#34;&gt;Migrate to Grafana Mimir using Jsonnet&lt;/a&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;This document was tested with Cortex versions 1.10 and 1.11.&lt;/p&gt;
&lt;p&gt;It might work with more recent versions of Cortex, but it&amp;rsquo;s not guaranteed.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;To migrate a Helm deployment of Cortex refer to &lt;a href=&#34;/docs/helm-charts/mimir-distributed/latest/migration-guides/migrate-from-cortex/&#34;&gt;Migrate from Cortex&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Grafana Mimir includes significant changes that simplify the deployment and continued operation of a horizontally scalable, multi-tenant time series database with long-term storage.&lt;/p&gt;
&lt;p&gt;The changes make Grafana Mimir easier to run out of the box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removed configuration parameters that don&amp;rsquo;t require tuning&lt;/li&gt;
&lt;li&gt;Renamed some parameters so that they&amp;rsquo;re more easily understood&lt;/li&gt;
&lt;li&gt;Updated the default values of some existing parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;mimirtool&lt;/code&gt; automates configuration conversion.
It provides a simple migration by generating Mimir configuration from Cortex configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before you begin:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ensure that you are running either Cortex 1.10.X or Cortex 1.11.X.&lt;/p&gt;
&lt;p&gt;If you are running an older version of Cortex, upgrade to &lt;a href=&#34;https://github.com/cortexproject/cortex/releases&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Cortex 1.11.1&lt;/a&gt; before proceeding with the migration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensure you have installed Cortex alerting and recording rules as well as Cortex dashboards.&lt;/p&gt;
&lt;p&gt;Using the monitoring mixin, you need to install both alerting and recording rules in either Prometheus or Cortex. You also need to install dashboards in Grafana.
To download a prebuilt ZIP file that contains the alerting and recording rules, refer to &lt;a href=&#34;https://github.com/grafana/cortex-jsonnet/releases/download/1.11.0/cortex-mixin.zip&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Release Cortex-jsonnet 1.11.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To upload rules to the ruler using mimirtool, refer to &lt;a href=&#34;../../../manage/tools/mimirtool/&#34;&gt;mimirtool rules&lt;/a&gt;.
To import the dashboards into Grafana, refer to &lt;a href=&#34;/docs/grafana/latest/dashboards/export-import/#import-dashboard&#34;&gt;Import dashboard&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;notable-changes&#34;&gt;Notable changes&lt;/h2&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 the full list of changes, refer to Mimir’s &lt;a href=&#34;https://github.com/grafana/mimir/blob/main/CHANGELOG.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;CHANGELOG&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Grafana Mimir HTTP server defaults to listening on port 8080; Cortex defaults to listening on port 80.
To maintain port 80 as the listening port, set &lt;code&gt;-server.http-listen-port=80&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grafana Mimir uses &lt;code&gt;anonymous&lt;/code&gt; as the default tenant ID when &lt;code&gt;-auth.multitenancy=false&lt;/code&gt;.
Cortex uses &lt;code&gt;fake&lt;/code&gt; as the default tenant ID when &lt;code&gt;-auth.enabled=false&lt;/code&gt;.
Use &lt;code&gt;-auth.no-auth-tenant=fake&lt;/code&gt; when &lt;code&gt;-auth.multitenancy=false&lt;/code&gt; to match the Cortex default tenant ID.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grafana Mimir removes the legacy HTTP prefixes deprecated in Cortex.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Query endpoints&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;Legacy&lt;/th&gt;
              &lt;th&gt;Current&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/query&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/query&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/query_range&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/query_range&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/query_exemplars&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/query_exemplars&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/series&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/series&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/labels&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/labels&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/label/{name}/values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/label/{name}/values&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/metadata&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/metadata&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/read&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/read&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/cardinality/label_names&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/cardinality/label_names&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/cardinality/label_values&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/cardinality/label_values&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/api/prom/user_stats&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/api/v1/user_stats&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Distributor endpoints&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;Legacy endpoint&lt;/th&gt;
              &lt;th&gt;Current&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/push&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/api/v1/push&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/all_user_stats&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/distributor/all_user_stats&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/ha-tracker&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/distributor/ha_tracker&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ingester endpoints&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;Legacy&lt;/th&gt;
              &lt;th&gt;Current&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/ring&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/ingester/ring&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/shutdown&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/ingester/shutdown&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/flush&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/ingester/flush&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/push&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/ingester/push&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ruler endpoints&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;Legacy&lt;/th&gt;
              &lt;th&gt;Current&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/rules&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/rules&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/api/v1/alerts&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/api/v1/alerts&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules/{namespace}/{groupName}&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules/{namespace}/{groupName}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules/{namespace}/{groupName}&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules/{namespace}/{groupName}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;lt;prometheus-http-prefix&amp;gt;/config/v1/rules/{namespace}&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/ruler_ring&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/ruler/ring&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alertmanager endpoints&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;Legacy&lt;/th&gt;
              &lt;th&gt;Current&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/&amp;lt;legacy-http-prefix&amp;gt;&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/alertmanager&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;/status&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/multitenant_alertmanager/status&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;generate-the-configuration-for-grafana-mimir&#34;&gt;Generate the configuration for Grafana Mimir&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../../../manage/tools/mimirtool/#config&#34;&gt;&lt;code&gt;mimirtool config convert&lt;/code&gt;&lt;/a&gt; command converts Cortex configuration to Mimir configuration. You can use it to update both flags and configuration files.&lt;/p&gt;
&lt;h3 id=&#34;install-mimirtool&#34;&gt;Install mimirtool&lt;/h3&gt;
&lt;p&gt;To install Mimirtool, download the appropriate binary from the &lt;a href=&#34;https://github.com/grafana/mimir/releases/latest&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;latest release&lt;/a&gt; for your operating system and architecture and make it executable.&lt;/p&gt;
&lt;p&gt;Alternatively, use a command line tool such as &lt;code&gt;curl&lt;/code&gt; to download &lt;code&gt;mimirtool&lt;/code&gt;. For example, for Linux with the AMD64 architecture, use the following 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;curl -fLo mimirtool https://github.com/grafana/mimir/releases/latest/download/mimirtool-linux-amd64
chmod &amp;#43;x mimirtool&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;use-mimirtool&#34;&gt;Use mimirtool&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;mimirtool config convert&lt;/code&gt; command converts Cortex 1.11 configuration files to Grafana Mimir configuration files.
It removes any configuration parameters that are no longer available in Grafana Mimir, and it renames configuration parameters that have a new name.
If you have explicitly set configuration parameters to a value matching the Cortex default, by default, &lt;code&gt;mimirtool config convert&lt;/code&gt; doesn&amp;rsquo;t update the value.
To have &lt;code&gt;mimirtool config convert&lt;/code&gt; update explicitly set values from the Cortex defaults to the new Grafana Mimir defaults, provide the &lt;code&gt;--update-defaults&lt;/code&gt; flag.
Refer to &lt;a href=&#34;../../../manage/tools/mimirtool/#convert&#34;&gt;convert&lt;/a&gt; for more information on using &lt;code&gt;mimirtool&lt;/code&gt; for configuration conversion.&lt;/p&gt;
&lt;h2 id=&#34;migrate-to-grafana-mimir-using-jsonnet&#34;&gt;Migrate to Grafana Mimir using Jsonnet&lt;/h2&gt;
&lt;p&gt;Grafana Mimir has a Jsonnet library that replaces the existing Cortex Jsonnet library and updated monitoring mixin.&lt;/p&gt;
&lt;h3 id=&#34;migrate-to-grafana-mimir-video&#34;&gt;Migrate to Grafana Mimir video&lt;/h3&gt;
&lt;p&gt;The following video shows you how to migrate to Grafana Mimir using Jsonnet.&lt;/p&gt;





  
  
  


&lt;div&gt;
  &lt;iframe src=&#34;https://player.vimeo.com/video/742056367?transparent=0&#34; title=&#34;vimeo video&#34; webkitallowfullscreen=&#34;&#34; mozallowfullscreen=&#34;&#34; allowfullscreen=&#34;&#34;&gt;&lt;/iframe&gt;
  &lt;div &gt;
    
  &lt;/div&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;h3 id=&#34;migrate-to-grafana-mimir-instructions&#34;&gt;Migrate to Grafana Mimir instructions&lt;/h3&gt;
&lt;p&gt;The following instructions describe how to migrate to Grafana Mimir using Jsonnet.&lt;/p&gt;
&lt;p&gt;To install the updated libraries using &lt;code&gt;jsonnet-bundler&lt;/code&gt;, run the following commands:&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;jb install github.com/grafana/mimir/operations/mimir@main
jb install github.com/grafana/mimir/operations/mimir-mixin@main&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;To deploy the updated Jsonnet:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the updated monitoring mixin.&lt;/p&gt;
&lt;p&gt;a. Add the dashboards to Grafana. The dashboards replace your Cortex dashboards and continue to work for monitoring Cortex deployments.&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;Resource dashboards are enabled by default and require additional metrics sources.
To understand the required metrics sources, refer to &lt;a href=&#34;../../../manage/monitor-grafana-mimir/requirements/#additional-resources-metrics&#34;&gt;Additional resources metrics&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;b. Install the recording and alerting rules into the ruler or a Prometheus server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the import of the Cortex Jsonnet library with the Mimir Jsonnet library.
For example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&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-jsonnet&#34;&gt;import &amp;#39;github.com/grafana/mimir/operations/mimir/mimir.libsonnet&amp;#39;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove the &lt;code&gt;cortex_&lt;/code&gt; prefix from any member keys of the &lt;code&gt;&amp;lt;MIMIR&amp;gt;._config&lt;/code&gt; object.
For example, &lt;code&gt;cortex_compactor_disk_data_size&lt;/code&gt; becomes &lt;code&gt;compactor_disk_data_size&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you are using the Cortex defaults, set the server HTTP port to 80.
The new Mimir default is 8080.
For example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&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-jsonnet&#34;&gt;(import &amp;#39;github.com/grafana/mimir/operations/mimir/mimir.libsonnet&amp;#39;) {
  _config&amp;#43;: {
    server_http_port: 80,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For each component, use &lt;code&gt;mimirtool&lt;/code&gt; to update the configured arguments.
To extract the flags for each component, refer to &lt;a href=&#34;../../../manage/tools/mimirtool/#extracting-flags-from-jsonnet&#34;&gt;Extracting flags from Jsonnet&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the updated Jsonnet&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To verify that the cluster is operating correctly, use the &lt;a href=&#34;../../../manage/monitor-grafana-mimir/dashboards/&#34;&gt;monitoring mixin dashboards&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="migrate-from-cortex-to-grafana-mimir">Migrate from Cortex to Grafana Mimir&lt;/h1>
&lt;p>As an operator, you can migrate a Jsonnet deployment of &lt;a href="https://cortexmetrics.io/" target="_blank" rel="noopener noreferrer">Cortex&lt;/a> to Grafana Mimir.
The overview includes the steps required for any environment. To migrate deployment environments with Jsonnet, see &lt;a href="#migrate-to-grafana-mimir-using-jsonnet">Migrate to Grafana Mimir using Jsonnet&lt;/a>.&lt;/p></description></item><item><title>Migrate from Thanos or Prometheus to Grafana Mimir</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-thanos-or-prometheus/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-thanos-or-prometheus/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-from-thanos-or-prometheus-to-grafana-mimir&#34;&gt;Migrate from Thanos or Prometheus to Grafana Mimir&lt;/h1&gt;
&lt;p&gt;This document guides an operator through the process of migrating a deployment of Thanos or Prometheus to Grafana Mimir.&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;Grafana Mimir stores series in TSDB blocks uploaded in an object storage bucket.
These blocks are the same as those used by Prometheus and Thanos.
Each project stores blocks in different places and uses slightly different block metadata files.&lt;/p&gt;
&lt;h2 id=&#34;configuring-remote-write-to-grafana-mimir&#34;&gt;Configuring remote write to Grafana Mimir&lt;/h2&gt;
&lt;p&gt;For configuration of remote write to Grafana Mimir, refer to &lt;a href=&#34;../../../manage/secure/authentication-and-authorization/#configuring-prometheus-remote-write&#34;&gt;Configuring Prometheus remote write&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;uploading-historic-tsdb-blocks-to-grafana-mimir&#34;&gt;Uploading historic TSDB blocks to Grafana Mimir&lt;/h2&gt;
&lt;p&gt;Grafana Mimir supports uploading of historic TSDB blocks, notably from Prometheus.
In order to enable this functionality, either for all tenants or a specific one, refer to
&lt;a href=&#34;../../../configure/configure-tsdb-block-upload/&#34;&gt;Configure TSDB block upload&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Prometheus stores TSDB blocks in the path specified in the &lt;code&gt;--storage.tsdb.path&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;To find all block directories in the TSDB &lt;code&gt;&amp;lt;STORAGE TSDB PATH&amp;gt;&lt;/code&gt;, run the following 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;find &amp;lt;STORAGE TSDB PATH&amp;gt; -name chunks -exec dirname {} \;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Grafana Mimir supports multiple tenants and stores blocks per tenant. With multi-tenancy disabled, there
is a single tenant called &lt;code&gt;anonymous&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Use Grafana mimirtool to upload each block, such as those identified by the previous command, to Grafana Mimir:&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 backfill --address=http://&amp;lt;mimir-hostname&amp;gt; --id=&amp;lt;tenant&amp;gt; &amp;lt;block1&amp;gt; &amp;lt;block2&amp;gt;...&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&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;If you need to authenticate against Grafana Mimir, you can provide an API key via the &lt;code&gt;--key&lt;/code&gt; flag, for example &lt;code&gt;--key=$(cat token.txt)&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Grafana Mimir performs some sanitization and validation of each block&amp;rsquo;s metadata.
As a result, it rejects Thanos blocks due to unsupported labels.
As a workaround, if you need to upload Thanos blocks, upload the blocks directly to the
Grafana Mimir blocks bucket, prefixed by &lt;code&gt;&amp;lt;tenant&amp;gt;/&amp;lt;block ID&amp;gt;/&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;block-metadata&#34;&gt;Block metadata&lt;/h2&gt;
&lt;p&gt;Each block has a &lt;code&gt;meta.json&lt;/code&gt; metadata file that is used by Grafana Mimir, Prometheus, and Thanos to identify the block contents.
Each project has its own metadata conventions.&lt;/p&gt;
&lt;p&gt;In the Grafana Mimir 2.1 (or earlier) release, the ingesters added an external label to the &lt;code&gt;meta.json&lt;/code&gt; file to identify the tenant that owns the block.&lt;/p&gt;
&lt;p&gt;In the Grafana Mimir 2.2 (or later) release, blocks no longer have a label that identifies the tenant.&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;Blocks from Prometheus don&amp;rsquo;t have any external labels stored in them.
Only blocks from Thanos use labels.&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;If you encounter the HTTP error 413 &amp;ldquo;Request Entity Too Large&amp;rdquo; when uploading blocks using mimirtool, and if Nginx is being used as a reverse proxy, the uploaded block size may be exceeding Nginx&amp;rsquo;s default maximum allowed request body size.
To resolve this issue:&lt;/p&gt;
&lt;p&gt;Determine the current size of the blocks you are trying to upload by running the following command(by default the blocks are sized around 500MB, but it can vary depending on the configuration of Prometheus or Thanos.)&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;find &amp;lt;path/to/blocks&amp;gt; -name &amp;#39;chunks&amp;#39; -printf &amp;#39;%s\n&amp;#39; | numfmt --to=iec-i&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This shows the size of each block&amp;rsquo;s chunks directory in a human-readable format.
Increase the client_max_body_size directive in the Nginx configuration:&lt;/p&gt;
&lt;p&gt;For manual Nginx deployments, open the Nginx configuration file (e.g., /etc/nginx/nginx.conf) and set the &lt;code&gt;client_max_body_size&lt;/code&gt; directive inside the server block for the Mimir endpoint to a value about 5% larger than the maximum size of the blocks you are uploading. 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;server {
    ...
    client_max_body_size 540M;
    ...
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&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;location / {
    ...
    client_max_body_size 540M;
    ...
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Helm deployments of Mimir, you can set the &lt;code&gt;gateway.nginx.config.clientMaxBodySize&lt;/code&gt; value in your Helm values file to a higher value, e.g.:&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;gateway:
  nginx:
    config:
      clientMaxBodySize: 540M&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Apply the configuration changes:&lt;/p&gt;
&lt;p&gt;For manual Nginx deployments, save the configuration file and reload Nginx:&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;sudo nginx -s reload&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Helm deployments, upgrade your Mimir release with the updated values file:&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;helm upgrade &amp;lt;release-name&amp;gt; &amp;lt;chart-name&amp;gt; -f values.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After increasing the &lt;code&gt;client_max_body_size&lt;/code&gt; setting, you can upload the blocks without encountering the 413 error.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;considerations-on-thanos-specific-features&#34;&gt;Considerations on Thanos specific features&lt;/h2&gt;
&lt;p&gt;Thanos requires that Prometheus is configured with external labels.
When the Thanos sidecar uploads blocks, it includes the external labels from Prometheus in the &lt;code&gt;meta.json&lt;/code&gt; file inside the block.
When you query the block, Thanos injects Prometheus’ external labels in the series returned in the query result.
Thanos also uses labels for the deduplication of replicated data.&lt;/p&gt;
&lt;p&gt;If you want to use existing blocks from Thanos by Grafana Mimir, there are some considerations:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grafana Mimir doesn&amp;rsquo;t inject external labels into query results.&lt;/strong&gt;
This means that blocks that were originally created by Thanos will not include their external labels in the results when queried by Grafana Mimir.
If you need to have external labels in your query results, this is currently not possible to achieve in Grafana Mimir.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grafana Mimir will not respect deduplication labels configured in Thanos when querying the blocks.&lt;/strong&gt;
For best query performance, only upload Thanos blocks from a single Prometheus replica from each HA pair.
If you upload blocks from both replicas, the query results returned by Mimir will include samples from both replicas.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grafana Mimir does not support Thanos’ &lt;em&gt;downsampling&lt;/em&gt; feature.&lt;/strong&gt;
To guarantee query results correctness please only upload original (raw) Thanos blocks into Mimir&amp;rsquo;s storage.
If you also upload blocks with downsampled data (ie. blocks with non-zero &lt;code&gt;Resolution&lt;/code&gt; field in &lt;code&gt;meta.json&lt;/code&gt; file), Grafana Mimir will merge raw samples and downsampled samples together at the query time.
This may cause that incorrect results are returned for the query.&lt;/p&gt;
&lt;h2 id=&#34;migrate-historic-tsdb-blocks-from-thanos-to-grafana-mimir&#34;&gt;Migrate historic TSDB blocks from Thanos to Grafana Mimir&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Copy the blocks from Thanos&amp;rsquo;s bucket to an Intermediate bucket.&lt;/p&gt;
&lt;p&gt;Create an intermediate object storage bucket (such as Amazon S3 or GCS) within your cloud provider, where you can copy the historical blocks and work on them before uploading them to the Mimir bucket.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-tip&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Tip&lt;/p&gt;&lt;p&gt;Run the commands within a &lt;code&gt;screen&lt;/code&gt; or &lt;code&gt;tmux&lt;/code&gt; session, to avoid any interruptions because the steps might take some time depending on the amount of data.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;For Amazon S3, use the &lt;code&gt;aws&lt;/code&gt; tool:&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;aws s3 cp --recursive s3://&amp;lt;THANOS-BUCKET&amp;gt; s3://&amp;lt;INTERMEDIATE-MIMIR-BUCKET&amp;gt;/&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Google Cloud Storage (GCS), use the &lt;code&gt;gsutil&lt;/code&gt; tool:&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;gsutil -m cp -r gs://&amp;lt;THANOS-BUCKET&amp;gt;/* gs://&amp;lt;INTERMEDIATE-MIMIR-BUCKET&amp;gt;/&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After the copy process completes, inspect the blocks in the bucket to make sure that they are valid from a Thanos perspective.&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;thanos tools bucket inspect \
    --objstore.config-file bucket.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove the downsampled blocks.&lt;/p&gt;
&lt;p&gt;Mimir doesn’t understand the downsampled blocks from Thanos, such as blocks with a non-zero &lt;code&gt;Resolution&lt;/code&gt; field in the &lt;code&gt;meta.json&lt;/code&gt; file. Therefore, you need to remove the &lt;code&gt;5m&lt;/code&gt; and &lt;code&gt;1h&lt;/code&gt; downsampled blocks from this bucket.&lt;/p&gt;
&lt;p&gt;Mark the downsampled blocks for deletion:&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;thanos tools bucket retention \
    --objstore.config-file bucket.yaml \
    --retention.resolution-1h=1s \
    --retention.resolution-5m=1s \
    --retention.resolution-raw=0s&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Cleanup the blocks marked for deletion.&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;thanos tools bucket cleanup \
    --objstore.config-file bucket.yaml \
    --delete-delay=0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove the duplicated blocks.&lt;/p&gt;
&lt;p&gt;If two replicas of Prometheus instances are deployed for high-availability, then only upload the blocks from one of the replicas and drop from the other replica.&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;# Get list of all blocks in the bucket
thanos tools bucket inspect \
    --objstore.config-file bucket.yaml \
    --output=tsv &amp;gt; blocks.tsv

# Find blocks from replica that we will drop
cat blocks.tsv| grep prometheus_replica=&amp;lt;PROMETHEUS-REPLICA-TO-DROP&amp;gt; \
    | awk &amp;#39;{print $1}&amp;#39; &amp;gt; blocks_to_drop.tsv

# Mark found blocks for deletion
for ID in $(cat blocks_to_drop.tsv)
do
    thanos tools bucket mark \
       --marker=&amp;#34;deletion-mark.json&amp;#34; \
       --objstore.config-file bucket.yaml \
       --details=&amp;#34;Removed as duplicate&amp;#34; \
       --id $ID
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&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;You must replace &lt;code&gt;prometheus_replica&lt;/code&gt; with the unique label that would differentiate Prometheus replicas in your setup.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Clean up the duplicate blocks marked for deletion again:&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;thanos tools bucket cleanup \
    --objstore.config-file bucket.yaml \
    --delete-delay=0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-tip&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Tip&lt;/p&gt;&lt;p&gt;If you want to visualize exactly what&amp;rsquo;s happening in the blocks, with respect to the source of blocks, external labels, compaction levels, and more, you can use the following command to get the output as CSV and import it into a spreadsheet:&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;thanos tools bucket inspect \
    --objstore.config-file bucket-prod.yaml \
    --output=csv &amp;gt; thanos-blocks.csv&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Relabel the blocks with external labels.&lt;/p&gt;
&lt;p&gt;Mimir doesn’t inject external labels from the &lt;code&gt;meta.json&lt;/code&gt; file into query results. Therefore, you need to relabel the blocks with the required external labels in the &lt;code&gt;meta.json&lt;/code&gt; file.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-tip&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Tip&lt;/p&gt;&lt;p&gt;You can get the external labels in the &lt;code&gt;meta.json&lt;/code&gt; file of each block from the CSV file that&amp;rsquo;s imported, and build the rewrite configuration accordingly.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;



&lt;div class=&#34;admonition admonition-tip&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Tip&lt;/p&gt;&lt;p&gt;Add the &lt;code&gt;__tenant_id__&lt;/code&gt; label with the value of your target tenant. This is important for Mimir to successfully query the migrated data when you enable tenant federation and configure the Grafana data source to query multiple tenants.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Create a rewrite configuration that is similar to this:&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;# relabel-config.yaml
- action: replace
  target_label: &amp;#34;&amp;lt;LABEL-KEY&amp;gt;&amp;#34;
  replacement: &amp;#34;&amp;lt;LABEL-VALUE&amp;gt;&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Perform the rewrite dry run to confirm all works well.&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;# Get list of all blocks in the bucket after removing the depuplicate and downsampled blocks.
thanos tools bucket inspect \
    --objstore.config-file bucket.yaml \
    --output=tsv &amp;gt; blocks-to-rewrite.tsv

# Check if rewrite of the blocks with external labels is working as expected.
for ID in $(cat blocks-to-rewrite.tsv)
do
    thanos tools bucket rewrite \
        --objstore.config-file bucket.yaml \
        --rewrite.to-relabel-config-file relabel-config.yaml \
        --dry-run \
        --id $ID
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;After you confirm that the rewrite is working as expected via &lt;code&gt;--dry-run&lt;/code&gt;, apply the changes with the &lt;code&gt;--no-dry-run&lt;/code&gt; flag. Remember to include &lt;code&gt;--delete-blocks&lt;/code&gt;, otherwise the original blocks will not be marked for deletion.&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;# Rewrite the blocks with external labels and mark the original blocks for deletion.
for ID in $(cat blocks-to-rewrite.tsv)
do
    thanos tools bucket rewrite  \
        --objstore.config-file bucket.yaml \
        --rewrite.to-relabel-config-file relabel-config.yaml \
        --no-dry-run \
        --delete-blocks \
        --id $ID
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The output of relabelling of every block would look like something below.&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;level=info ts=2022-10-10T13:03:32.032820262Z caller=factory.go:50 msg=&amp;#34;loading bucket configuration&amp;#34;
level=info ts=2022-10-10T13:03:32.516953867Z caller=tools_bucket.go:1160 msg=&amp;#34;downloading block&amp;#34; source=01GEGWPME2187SVFH63G8DH7KH
level=info ts=2022-10-10T13:03:35.825009556Z caller=tools_bucket.go:1197 msg=&amp;#34;changelog will be available&amp;#34; file=/tmp/thanos-  rewrite/01GF0ZWPWGEPHG5NV79NH9KMPV/change.log
level=info ts=2022-10-10T13:03:35.836953593Z caller=tools_bucket.go:1212 msg=&amp;#34;starting rewrite for block&amp;#34; source=01GEGWPME2187SVFH63G8DH7KH  new=01GF0ZWPWGEPHG5NV79NH9KMPV toDelete= toRelabel=&amp;#34;- action: replace\n  target_label: \&amp;#34;cluster\&amp;#34;\n  replacement: \&amp;#34;prod-cluster\&amp;#34;\n&amp;#34;
level=info ts=2022-10-10T13:04:47.57624244Z caller=compactor.go:42 msg=&amp;#34;processed 10.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:04:53.4046885Z caller=compactor.go:42 msg=&amp;#34;processed 20.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:04:59.649337602Z caller=compactor.go:42 msg=&amp;#34;processed 30.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:02.986219042Z caller=compactor.go:42 msg=&amp;#34;processed 40.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:05.990498497Z caller=compactor.go:42 msg=&amp;#34;processed 50.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:09.349918024Z caller=compactor.go:42 msg=&amp;#34;processed 60.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:12.040895624Z caller=compactor.go:42 msg=&amp;#34;processed 70.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:15.253899238Z caller=compactor.go:42 msg=&amp;#34;processed 80.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:18.471471014Z caller=compactor.go:42 msg=&amp;#34;processed 90.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:21.536267363Z caller=compactor.go:42 msg=&amp;#34;processed 100.00% of 701243 series&amp;#34;
level=info ts=2022-10-10T13:05:21.536466158Z caller=tools_bucket.go:1222 msg=&amp;#34;wrote new block after modifications; flushing&amp;#34; source=01GEGWPME2187SVFH63G8DH7KH new=01GF0ZWPWGEPHG5NV79NH9KMPV
level=info ts=2022-10-10T13:05:28.675240198Z caller=tools_bucket.go:1231 msg=&amp;#34;uploading new block&amp;#34; source=01GEGWPME2187SVFH63G8DH7KH new=01GF0ZWPWGEPHG5NV79NH9KMPV
level=info ts=2022-10-10T13:05:38.922348564Z caller=tools_bucket.go:1241 msg=uploaded source=01GEGWPME2187SVFH63G8DH7KH new=01GF0ZWPWGEPHG5NV79NH9KMPV
level=info ts=2022-10-10T13:05:38.979696873Z caller=block.go:203 msg=&amp;#34;block has been marked for deletion&amp;#34; block=01GEGWPME2187SVFH63G8DH7KH
level=info ts=2022-10-10T13:05:38.979832767Z caller=tools_bucket.go:1249 msg=&amp;#34;rewrite done&amp;#34; IDs=01GEGWPME2187SVFH63G8DH7KH
level=info ts=2022-10-10T13:05:38.980197796Z caller=main.go:161 msg=exiting&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Cleanup the original blocks which are marked for deletion.&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;thanos tools bucket cleanup \
    --objstore.config-file bucket.yaml \
    --delete-delay=0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&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;If there are multiple Prometheus clusters, then relabelling each of them in parallel may speed up the entire process.&lt;/p&gt;
&lt;p&gt;Get the list of blocks that for each cluster, and process it separately.&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;thanos tools bucket inspect \
    --objstore.config-file bucket.yaml \
    --output=tsv \
    | grep &amp;lt;PROMETHEUS-CLUSTER-NAME&amp;gt; \
    | awk &amp;#39;{print $1}&amp;#39; &amp;gt; prod-blocks.tsv&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;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;for ID in `cat prod-blocks.tsv`
do
    thanos tools bucket rewrite  \
       --objstore.config-file bucket.yaml \
       --rewrite.to-relabel-config-file relabel-config.yaml \
       --delete-blocks \
       --no-dry-run \
       --id $ID
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove external labels from meta.json.&lt;/p&gt;
&lt;p&gt;Mimir compactor will not be able to compact the blocks having external labels with Mimir&amp;rsquo;s own blocks that don&amp;rsquo;t have any such labels in their meta.json. Therefore these external labels have to be removed before copying them to the Mimir bucket.&lt;/p&gt;
&lt;p&gt;Use the below script to remove the labels from the meta.json.&lt;/p&gt;
&lt;p&gt;For Amazon S3, use the &lt;code&gt;aws&lt;/code&gt; tool:&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;#!/bin/bash

BUCKET=&amp;#34;XXX&amp;#34;

echo &amp;#34;Fetching list of meta.json files (this can take a while if there are many blocks)&amp;#34;
aws s3 ls $BUCKET --recursive | awk &amp;#39;{print $4}&amp;#39; | grep meta.json | grep -v meta.json.orig &amp;gt; meta-files.txt

echo &amp;#34;Processing meta.json files&amp;#34;
for FILE in $(cat meta-files.txt); do
   echo &amp;#34;Removing Thanos labels from $FILE&amp;#34;
   ORIG_META_JSON=$(aws s3 cp s3://$BUCKET/$FILE -)
   UPDATED_META_JSON=$(echo &amp;#34;$ORIG_META_JSON&amp;#34; | jq &amp;#34;del(.thanos.labels)&amp;#34;)

   if ! diff -u &amp;lt;( echo &amp;#34;$ORIG_META_JSON&amp;#34; | jq . ) &amp;lt;( echo &amp;#34;$UPDATED_META_JSON&amp;#34; | jq .) &amp;gt; /dev/null; then
     echo &amp;#34;Backing up $FILE to $FILE.orig&amp;#34;
     aws s3 cp &amp;#34;s3://$BUCKET/$FILE&amp;#34; &amp;#34;s3://$BUCKET/$FILE.orig&amp;#34;
     echo &amp;#34;Uploading modified $FILE&amp;#34;
     echo &amp;#34;$UPDATED_META_JSON&amp;#34; | aws s3 cp - &amp;#34;s3://$BUCKET/$FILE&amp;#34;
   else
     echo &amp;#34;No diff for $FILE&amp;#34;
   fi
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Google Cloud Storage (GCS), use the gsutil tool:&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;#!/bin/bash

BUCKET=&amp;#34;GCS Bucket name&amp;#34;

echo &amp;#34;Fetching list of meta.json files (this can take a while if there are many blocks)&amp;#34;
gsutil ls &amp;#34;gs://$BUCKET/*/meta.json&amp;#34; &amp;gt; meta-files.txt

echo &amp;#34;Processing meta.json files&amp;#34;
for FILE in $(cat meta-files.txt); do
   echo &amp;#34;Removing Thanos labels from $FILE&amp;#34;
   ORIG_META_JSON=$(gsutil cat &amp;#34;$FILE&amp;#34;)
   UPDATED_META_JSON=$(echo &amp;#34;$ORIG_META_JSON&amp;#34; | jq &amp;#34;del(.thanos.labels)&amp;#34;)

   if ! diff -u &amp;lt;( echo &amp;#34;$ORIG_META_JSON&amp;#34; | jq . ) &amp;lt;( echo &amp;#34;$UPDATED_META_JSON&amp;#34; | jq .) &amp;gt; /dev/null; then
      echo &amp;#34;Backing up $FILE to $FILE.orig&amp;#34;
      gsutil cp &amp;#34;$FILE&amp;#34; &amp;#34;$FILE.orig&amp;#34;
      echo &amp;#34;Uploading modified $FILE&amp;#34;
      echo &amp;#34;$UPDATED_META_JSON&amp;#34; | gsutil cp - &amp;#34;$FILE&amp;#34;
   else
      echo &amp;#34;No diff for $FILE&amp;#34;
   fi
done&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the blocks from the intermediate bucket to the Mimir bucket.&lt;/p&gt;
&lt;p&gt;For Amazon S3, use the &lt;code&gt;aws&lt;/code&gt; tool:&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;aws s3 cp --recursive s3://&amp;lt;INTERMEDIATE-MIMIR-BUCKET&amp;gt; s3://&amp;lt;MIMIR-AWS-BUCKET&amp;gt;/&amp;lt;TENANT&amp;gt;/&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For Google Cloud Storage (GCS), use the gsutil tool:&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;gsutil -m cp -r gs://&amp;lt;INTERMEDIATE-MIMIR-BUCKET&amp;gt; gs://&amp;lt;MIMIR-GCS-BUCKET&amp;gt;/&amp;lt;TENANT&amp;gt;/&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Historical blocks are not available for querying immediately after they are uploaded because the bucket index with the list of all available blocks first needs to be updated by the compactor. The compactor typically perform such an update every 15 minutes. After an update completes, other components such as the querier or store-gateway are able to work with the historical blocks, and the blocks are available for querying through Grafana.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check the &lt;code&gt;store-gateway&lt;/code&gt; HTTP endpoint at &lt;code&gt;http://&amp;lt;STORE-GATEWAY-ENDPOINT&amp;gt;/store-gateway/tenant/&amp;lt;TENANT-NAME&amp;gt;/blocks&lt;/code&gt; to verify that the uploaded blocks are there.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="migrate-from-thanos-or-prometheus-to-grafana-mimir">Migrate from Thanos or Prometheus to Grafana Mimir&lt;/h1>
&lt;p>This document guides an operator through the process of migrating a deployment of Thanos or Prometheus to Grafana Mimir.&lt;/p></description></item><item><title>Migrate from Thanos to Mimir using Thanos sidecar</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-thanos-to-mimir-with-thanos-sidecar/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-from-thanos-to-mimir-with-thanos-sidecar/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-from-thanos-to-mimir-using-thanos-sidecar&#34;&gt;Migrate from Thanos to Mimir using Thanos sidecar&lt;/h1&gt;
&lt;p&gt;As an operator, you can migrate a deployment of Thanos to Grafana Mimir by using Thanos sidecar to move metrics over with a stepped workflow.&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;An option when migrating is to allow Thanos to query Mimir. This way you retain historical data via your existing Thanos deployment while pointing all of your Prometheus servers (or Grafana Alloy and other metric sources) to Mimir.&lt;/p&gt;
&lt;p&gt;The overall setup consists of setting up Thanos Sidecar alongside Mimir and then pointing Thanos Query to the sidecar as if it was just a normal sidecar.&lt;/p&gt;
&lt;p&gt;This is not so much of a guide as it is a collection of configurations that have been used with success prior.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This setup is unsupported, experimental and has not been battle tested. Your mileage may vary, ensure you have tested this for your use case and have made appropriate backups (and tested your procedures for recovery)&lt;/p&gt;
&lt;h2 id=&#34;technical-details&#34;&gt;Technical details&lt;/h2&gt;
&lt;p&gt;There are very few obstacles to get this working properly. Thanos Sidecar is designed to work with the Prometheus API which Mimir (almost) implements. There are only 2 endpoints that are not implemented that we need to &amp;ldquo;spoof&amp;rdquo; to get Thanos sidecar to believe it is connecting to a Prometheus server: &lt;code&gt;/api/v1/status/buildinfo&lt;/code&gt; and &lt;code&gt;/api/v1/status/config&lt;/code&gt;. We spoof these endpoints using NGINX (more details later).&lt;/p&gt;
&lt;p&gt;In addition, you need to handle the &lt;code&gt;/metrics&lt;/code&gt; endpoint of the Prometheus server through NGINX configuration. Since Thanos version &lt;code&gt;v0.37.0&lt;/code&gt;, the sidecar evaluates the &lt;code&gt;prometheus_tsdb_lowest_timestamp_seconds&lt;/code&gt; to get the lowest timestamp in the TSDB database. Refer to &lt;a href=&#34;https://github.com/thanos-io/thanos/pull/7820&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://github.com/thanos-io/thanos/pull/7820&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The only other roadblock is the requirement for requests to Mimir to contain the &lt;code&gt;X-Scope-Org-Id&lt;/code&gt; header to identify the Tenant. We inject this header using another NGINX container sitting in between Thanos Sidecar and Mimir.&lt;/p&gt;
&lt;p&gt;In our case, everything was being deployed in Kubernetes. Mimir was deployed using the &lt;code&gt;mimir-distributed&lt;/code&gt; helm chart. Therefore configurations shown will be Kubernetes manifests that will need to be modified for your environment. If you are not using Kubernetes then you will need to set up the appropriate configuration for NGINX to implement the technical setup described above. You may use the configurations below for inspiration but they will not work out of the box.&lt;/p&gt;
&lt;h2 id=&#34;deploy-thanos-sidecar&#34;&gt;Deploy Thanos sidecar&lt;/h2&gt;
&lt;p&gt;We deployed the sidecar using Kubernetes using the below manifest:&lt;/p&gt;
&lt;h3 id=&#34;deployment&#34;&gt;Deployment&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;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;apiVersion: apps/v1
kind: Deployment
metadata:
  name: thanos-sidecar
  namespace: mimir
  labels:
    app: thanos-sidecar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: thanos-sidecar
  template:
    metadata:
      labels:
        app: thanos-sidecar
    spec:
      volumes:
        - name: config
          configMap:
            name: sidecar-nginx
            defaultMode: 420
      containers:
        - name: nginx
          image: nginxinc/nginx-unprivileged:1.19-alpine
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          volumeMounts:
            - name: config
              mountPath: /etc/nginx
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
        - name: thanos-sidecar
          image: quay.io/thanos/thanos:v0.26.0
          args:
            - sidecar
            - &amp;#34;--prometheus.url=http://localhost:8080/prometheus&amp;#34;
            - &amp;#34;--grpc-address=:10901&amp;#34;
            - &amp;#34;--http-address=:10902&amp;#34;
            - &amp;#34;--log.level=info&amp;#34;
            - &amp;#34;--log.format=logfmt&amp;#34;
          ports:
            - name: http
              containerPort: 10902
              protocol: TCP
            - name: grpc
              containerPort: 10901
              protocol: TCP
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;service&#34;&gt;Service&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;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;apiVersion: v1
kind: Service
metadata:
  name: thanos-sidecar
  namespace: mimir
  labels:
    app: thanos-sidecar
spec:
  ports:
    - name: 10901-10901
      protocol: TCP
      port: 10901
      targetPort: 10901
  selector:
    app: thanos-sidecar
  type: ClusterIP&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;nginx-configuration-for-thanos-sidecar&#34;&gt;NGINX configuration for Thanos sidecar&lt;/h2&gt;
&lt;p&gt;Notice that there is an NGINX container within the sidecar deployment definition. This NGINX instance sits between the sidecar and Mimir (ie. &lt;code&gt;sidecar --&amp;gt; nginx --&amp;gt; mimir&lt;/code&gt;) it is responsible for injecting the tenant ID into the requests from the sidecar to Mimir. The configuration that this NGINX instance uses is as follows:&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;conf&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-conf&#34;&gt;worker_processes  5;  ## Default: 1
error_log  /dev/stderr;
pid        /tmp/nginx.pid;
worker_rlimit_nofile 8192;

events {
  worker_connections  4096;  ## Default: 1024
}

http {
  client_body_temp_path /tmp/client_temp;
  proxy_temp_path       /tmp/proxy_temp_path;
  fastcgi_temp_path     /tmp/fastcgi_temp;
  uwsgi_temp_path       /tmp/uwsgi_temp;
  scgi_temp_path        /tmp/scgi_temp;

  default_type application/octet-stream;
  log_format   main &amp;#39;$remote_addr - $remote_user [$time_local]  $status &amp;#39;
        &amp;#39;&amp;#34;$request&amp;#34; $body_bytes_sent &amp;#34;$http_referer&amp;#34; &amp;#39;
        &amp;#39;&amp;#34;$http_user_agent&amp;#34; &amp;#34;$http_x_forwarded_for&amp;#34;&amp;#39;;
  access_log   /dev/stderr  main;

  sendfile     on;
  tcp_nopush   on;
  resolver kube-dns.kube-system.svc.cluster.local;

  server {
    listen 8080;

    # Distributor endpoints
    location / {
      proxy_set_header X-Scope-OrgID 1;
      proxy_pass      http://mimir-distributed-nginx.mimir.svc.cluster.local:80$request_uri;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;nginx-configuration-for-mimir&#34;&gt;NGINX configuration for Mimir&lt;/h2&gt;
&lt;p&gt;Now we modified the Mimir Distributed NGINX configuration to allow the sidecar to fetch the &amp;ldquo;external labels&amp;rdquo; and the &amp;ldquo;version&amp;rdquo; of our &amp;ldquo;Prometheus&amp;rdquo; server. You should be careful with the external labels to make sure that you don&amp;rsquo;t override any existing labels (in our case we used &amp;ldquo;source=&amp;lsquo;mimir&amp;rsquo;&amp;rdquo;). You should also consider existing dashboards and make sure that they will continue to work as expected. Make sure to test your setup first.&lt;/p&gt;
&lt;p&gt;In particular, these location blocks were added (full config further down):&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;conf&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-conf&#34;&gt;location /prometheus/api/v1/status/config {
        add_header Content-Type application/json;
        return 200 &amp;#34;{\&amp;#34;status\&amp;#34;:\&amp;#34;success\&amp;#34;,\&amp;#34;data\&amp;#34;:{\&amp;#34;yaml\&amp;#34;: \&amp;#34;global:\\n  external_labels:\\n    source: mimir\&amp;#34;}}&amp;#34;;
    }

location /prometheus/api/v1/status/buildinfo {
        add_header Content-Type application/json;
        return 200 &amp;#34;{\&amp;#34;status\&amp;#34;:\&amp;#34;success\&amp;#34;,\&amp;#34;data\&amp;#34;:{\&amp;#34;version\&amp;#34;:\&amp;#34;2.35.0\&amp;#34;,\&amp;#34;revision\&amp;#34;:\&amp;#34;6656cd29fe6ac92bab91ecec0fe162ef0f187654\&amp;#34;,\&amp;#34;branch\&amp;#34;:\&amp;#34;HEAD\&amp;#34;,\&amp;#34;buildUser\&amp;#34;:\&amp;#34;root@cf6852b14d68\&amp;#34;,\&amp;#34;buildDate\&amp;#34;:\&amp;#34;20220421-09:53:42\&amp;#34;,\&amp;#34;goVersion\&amp;#34;:\&amp;#34;go1.18.1\&amp;#34;}}&amp;#34;;
    }

location /prometheus/metrics {
        gzip on;
        gzip_types text/plain
        add_header &amp;#34;Content-Encoding&amp;#34; &amp;#34;gzip&amp;#34;;
        add_header &amp;#34;Content-Type&amp;#34; &amp;#34;text/plain; version=1.0.0; escaping=underscores&amp;#34;;
        return 200 &amp;#34;# HELP prometheus_tsdb_lowest_timestamp_seconds Lowest timestamp value stored in the database.\n# TYPE prometheus_tsdb_lowest_timestamp_seconds gauge\nprometheus_tsdb_lowest_timestamp_seconds 0\n&amp;#34;;
    }&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You need to modify the first one to set your external labels. The second one just allows Thanos to detect the version of Prometheus running. The third one fakes the metrics endpoint of the Prometheus server and returns the &lt;code&gt;prometheus_tsdb_lowest_timestamp_seconds&lt;/code&gt; metric with a value of &lt;code&gt;0&lt;/code&gt; which disables setting the min time within the Thanos sidecar.&lt;/p&gt;
&lt;p&gt;To modify the external labels alter this string: &lt;code&gt;&amp;quot;{\&amp;quot;status\&amp;quot;:\&amp;quot;success\&amp;quot;,\&amp;quot;data\&amp;quot;:{\&amp;quot;yaml\&amp;quot;: \&amp;quot;global:\\n external_labels:\\n source: mimir\&amp;quot;}}&amp;quot;&lt;/code&gt;. You will notice it is escaped JSON. Simply add elements to the &lt;code&gt;data.external_labels&lt;/code&gt; field to add more external labels as required or alter the existing key to modify them.&lt;/p&gt;
&lt;h3 id=&#34;full-mimir-distributed-nginx-configuration&#34;&gt;Full Mimir distributed NGINX configuration&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;conf&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-conf&#34;&gt;worker_processes  5;  ## Default: 1
error_log  /dev/stderr;
pid        /tmp/nginx.pid;
worker_rlimit_nofile 8192;

events {
  worker_connections  4096;  ## Default: 1024
}

http {
  client_body_temp_path /tmp/client_temp;
  proxy_temp_path       /tmp/proxy_temp_path;
  fastcgi_temp_path     /tmp/fastcgi_temp;
  uwsgi_temp_path       /tmp/uwsgi_temp;
  scgi_temp_path        /tmp/scgi_temp;

  default_type application/octet-stream;
  log_format   main &amp;#39;$remote_addr - $remote_user [$time_local]  $status &amp;#39;
        &amp;#39;&amp;#34;$request&amp;#34; $body_bytes_sent &amp;#34;$http_referer&amp;#34; &amp;#39;
        &amp;#39;&amp;#34;$http_user_agent&amp;#34; &amp;#34;$http_x_forwarded_for&amp;#34;&amp;#39;;
  access_log   /dev/stderr  main;

  sendfile     on;
  tcp_nopush   on;
  resolver kube-dns.kube-system.svc.cluster.local;

  server {
    listen 8080;

    location = / {
      return 200 &amp;#39;OK&amp;#39;;
      auth_basic off;
    }

    # Distributor endpoints
    location /distributor {
      proxy_pass      http://mimir-distributed-distributor.mimir.svc.cluster.local:8080$request_uri;
    }
    location = /api/v1/push {
      proxy_pass      http://mimir-distributed-distributor.mimir.svc.cluster.local:8080$request_uri;
    }

    # Alertmanager endpoints
    location /alertmanager {
      proxy_pass      http://mimir-distributed-alertmanager.mimir.svc.cluster.local:8080$request_uri;
    }
    location = /multitenant_alertmanager/status {
      proxy_pass      http://mimir-distributed-alertmanager.mimir.svc.cluster.local:8080$request_uri;
    }
    location = /api/v1/alerts {
      proxy_pass      http://mimir-distributed-alertmanager.mimir.svc.cluster.local:8080$request_uri;
    }

    # Ruler endpoints
    location /prometheus/config/v1/rules {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }
    location /prometheus/api/v1/rules {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }

    location /api/v1/rules {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }
    location /prometheus/api/v1/alerts {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }
    location /prometheus/rules {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }
    location = /ruler/ring {
      proxy_pass      http://mimir-distributed-ruler.mimir.svc.cluster.local:8080$request_uri;
    }

    location /prometheus/api/v1/status/config {
      add_header Content-Type application/json;
      return 200 &amp;#34;{\&amp;#34;status\&amp;#34;:\&amp;#34;success\&amp;#34;,\&amp;#34;data\&amp;#34;:{\&amp;#34;yaml\&amp;#34;: \&amp;#34;global:\\n  external_labels:\\n    source: mimir\&amp;#34;}}&amp;#34;;
    }

    location /prometheus/api/v1/status/buildinfo {
      add_header Content-Type application/json;
      return 200 &amp;#34;{\&amp;#34;status\&amp;#34;:\&amp;#34;success\&amp;#34;,\&amp;#34;data\&amp;#34;:{\&amp;#34;version\&amp;#34;:\&amp;#34;2.35.0\&amp;#34;,\&amp;#34;revision\&amp;#34;:\&amp;#34;6656cd29fe6ac92bab91ecec0fe162ef0f187654\&amp;#34;,\&amp;#34;branch\&amp;#34;:\&amp;#34;HEAD\&amp;#34;,\&amp;#34;buildUser\&amp;#34;:\&amp;#34;root@cf6852b14d68\&amp;#34;,\&amp;#34;buildDate\&amp;#34;:\&amp;#34;20220421-09:53:42\&amp;#34;,\&amp;#34;goVersion\&amp;#34;:\&amp;#34;go1.18.1\&amp;#34;}}&amp;#34;;
    }

    location /prometheus/metrics {
      gzip on;
      gzip_types text/plain
      add_header &amp;#34;Content-Encoding&amp;#34; &amp;#34;gzip&amp;#34;;
      add_header &amp;#34;Content-Type&amp;#34; &amp;#34;text/plain; version=1.0.0; escaping=underscores&amp;#34;;
      return 200 &amp;#34;# HELP prometheus_tsdb_lowest_timestamp_seconds Lowest timestamp value stored in the database.\n# TYPE prometheus_tsdb_lowest_timestamp_seconds gauge\nprometheus_tsdb_lowest_timestamp_seconds 0\n&amp;#34;;
    }

    # Rest of /prometheus goes to the query frontend
    location /prometheus {
      proxy_pass      http://mimir-distributed-query-frontend.mimir.svc.cluster.local:8080$request_uri;
    }

    # Buildinfo endpoint can go to any component
    location = /api/v1/status/buildinfo {
      proxy_pass      http://mimir-distributed-query-frontend.mimir.svc.cluster.local:8080$request_uri;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="migrate-from-thanos-to-mimir-using-thanos-sidecar">Migrate from Thanos to Mimir using Thanos sidecar&lt;/h1>
&lt;p>As an operator, you can migrate a deployment of Thanos to Grafana Mimir by using Thanos sidecar to move metrics over with a stepped workflow.&lt;/p></description></item><item><title>Migrate from classic to ingest storage architecture</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-ingest-storage/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/migrate/migrate-ingest-storage/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-from-classic-to-ingest-storage-architecture&#34;&gt;Migrate from classic to ingest storage architecture&lt;/h1&gt;
&lt;p&gt;Migrate from a Grafana Mimir cluster running with classic architecture to one running with ingest storage architecture. This process allows you to migrate without downtime by temporarily running two clusters in parallel and duplicating writes. For background on the different architectures, refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/get-started/about-grafana-mimir-architecture/&#34;&gt;Grafana Mimir architecture&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;This procedure temporarily doubles your ingestion and storage costs, because both clusters run in parallel and receive duplicated writes.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Follow these steps to migrate your Grafana Mimir cluster from classic architecture to ingest storage architecture.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;#before-you-begin&#34;&gt;Before you begin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#prepare-your-existing-grafana-mimir-cluster-for-migration&#34;&gt;Prepare your existing Grafana Mimir cluster for migration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#set-up-a-new-grafana-mimir-cluster-with-ingest-storage&#34;&gt;Set up a new Grafana Mimir cluster with ingest storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#configure-write-clients-to-duplicate-writes&#34;&gt;Configure write clients to duplicate writes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#wait-until-both-clusters-have-a-complete-view-of-the-data&#34;&gt;Wait until both clusters have a complete view of the data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#switch-read-clients-to-the-new-cluster&#34;&gt;Switch read clients to the new cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#scale-down-compactors-in-the-old-cluster&#34;&gt;Scale down compactors in the old cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#scale-out-compactors-in-the-new-cluster&#34;&gt;Scale out compactors in the new cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#update-ruler-alerting-configuration&#34;&gt;Update ruler alerting configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#stop-writing-to-the-old-cluster&#34;&gt;Stop writing to the old cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#decommission-the-old-cluster&#34;&gt;Decommission the old cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#scale-down-compactors-in-the-new-cluster&#34;&gt;Scale down compactors in the new cluster&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An existing Mimir cluster running with classic architecture.&lt;/li&gt;
&lt;li&gt;Access to deploy and configure a second Mimir cluster.&lt;/li&gt;
&lt;li&gt;Write clients, for example, Prometheus or OpenTelemetry Collector, that you can configure to send data to multiple endpoints.&lt;/li&gt;
&lt;li&gt;Read clients, for example, Grafana, that you can reconfigure to point to a new endpoint.&lt;/li&gt;
&lt;li&gt;The ability to modify Helm or Jsonnet configurations for both clusters.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;prepare-your-existing-grafana-mimir-cluster-for-migration&#34;&gt;Prepare your existing Grafana Mimir cluster for migration&lt;/h2&gt;
&lt;p&gt;Before creating a new Grafana Mimir cluster, temporarily scale out compactors in your existing cluster. This step helps handle the increased number of blocks created while both clusters are writing to the same object storage bucket.&lt;/p&gt;
&lt;h2 id=&#34;set-up-a-new-grafana-mimir-cluster-with-ingest-storage&#34;&gt;Set up a new Grafana Mimir cluster with ingest storage&lt;/h2&gt;
&lt;p&gt;Deploy a new Grafana Mimir cluster that uses ingest storage. Configure the new cluster to use the same object storage bucket as the old cluster.&lt;/p&gt;
&lt;p&gt;To prevent conflicts, disable the compactor, as shown in the following Helm values file sample:&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;compactor:
  replicas: 0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This configuration lets the new cluster use existing blocks from the old cluster while avoiding block overwrites.&lt;/p&gt;
&lt;p&gt;Optionally, to avoid duplicate alerts, disable alert sending from the ruler. For example, if you&amp;rsquo;re using the Helm chart:&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;mimir:
structuredConfig:
  limits:
    ruler_alerting_rules_evaluation_enabled: false

# or

ruler:
extraArgs:
  ruler.alerting-rules-evaluation-enabled: false&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If your alert delivery system, for example, Grafana OnCall or PagerDuty, already deduplicates alerts, you can skip this step.&lt;/p&gt;
&lt;p&gt;For setup instructions, refer to the existing &lt;a href=&#34;/docs/helm-charts/mimir-distributed/latest/run-production-environment-with-helm/&#34;&gt;Helm chart&lt;/a&gt; or 
    &lt;a href=&#34;/docs/mimir/v3.1.x/set-up/jsonnet/configure-ingest-storage/&#34;&gt;Jsonnet&lt;/a&gt; configuration documentation for ingest storage.&lt;/p&gt;
&lt;p&gt;After completing this step, open the Mimir overview dashboards for both clusters and verify that all components are healthy. Check that ingestion and querying are succeeding and that there are no gaps or errors.&lt;/p&gt;
&lt;h2 id=&#34;configure-write-clients-to-duplicate-writes&#34;&gt;Configure write clients to duplicate writes&lt;/h2&gt;
&lt;p&gt;Configure all write clients, such as Prometheus servers and OpenTelemetry Collectors, to send metrics to both clusters simultaneously.&lt;/p&gt;
&lt;p&gt;This ensures that the new cluster receives all recent samples while it accesses historical blocks from object storage.&lt;/p&gt;
&lt;p&gt;Keep read clients, such as Grafana, configured to use the old cluster during this step.&lt;/p&gt;
&lt;p&gt;After completing this step, open the Mimir overview dashboards for both clusters and verify that all components are healthy. Check that ingestion and querying are succeeding and that there are no gaps or errors.&lt;/p&gt;
&lt;h2 id=&#34;wait-until-both-clusters-have-a-complete-view-of-the-data&#34;&gt;Wait until both clusters have a complete view of the data&lt;/h2&gt;
&lt;p&gt;Keep write duplication running long enough for both clusters to have a complete view of recent data.&lt;/p&gt;
&lt;p&gt;Ingesters in the old cluster continuously upload new blocks to object storage and create new blocks on disk every 2 hours. Because ingesters typically hold about 12–13 hours of recent data in memory and on local disk, continue double writing for at least that duration. This ensures that the new cluster receives all data written during the overlap period and that queries return a complete dataset.&lt;/p&gt;
&lt;p&gt;You don’t need to disable block uploads from ingesters in the new cluster. Both clusters can safely upload blocks to the shared object storage because compactors merge them correctly.&lt;/p&gt;
&lt;p&gt;After the migration is complete, scale the compactors in the new cluster back down to their normal count.&lt;/p&gt;
&lt;h2 id=&#34;switch-read-clients-to-the-new-cluster&#34;&gt;Switch read clients to the new cluster&lt;/h2&gt;
&lt;p&gt;Update read clients, like Grafana, to query the new cluster.&lt;/p&gt;
&lt;p&gt;Verify that the old cluster is no longer receiving queries by checking for &lt;code&gt;msg=&amp;quot;query stats&amp;quot;&lt;/code&gt; entries in the query-frontend logs.&lt;/p&gt;
&lt;p&gt;After completing this step, open the Mimir overview dashboards for both clusters and verify that all components are healthy. Check that ingestion and querying are succeeding and that there are no gaps or errors.&lt;/p&gt;
&lt;h2 id=&#34;scale-down-compactors-in-the-old-cluster&#34;&gt;Scale down compactors in the old cluster&lt;/h2&gt;
&lt;p&gt;Reduce the number of compactor replicas in the old cluster to zero. For example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;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;compactor:
  replicas: 0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Run this step immediately before scaling up the compactors in the new cluster, ideally within 15 minutes. If the bucket index isn’t updated by the new cluster’s compactors within about an hour of stopping the old compactors, read queries can fail.&lt;/p&gt;
&lt;h2 id=&#34;scale-out-compactors-in-the-new-cluster&#34;&gt;Scale out compactors in the new cluster&lt;/h2&gt;
&lt;p&gt;Increase the number of compactor replicas in the new cluster to match the old configuration. This activates compaction in the new cluster and completes the transition for background storage management.&lt;/p&gt;
&lt;p&gt;After completing this step, open the Mimir overview dashboards for both clusters and verify that all components are healthy. Check that ingestion and querying are succeeding and that there are no gaps or errors.&lt;/p&gt;
&lt;h2 id=&#34;update-ruler-alerting-configuration&#34;&gt;Update ruler alerting configuration&lt;/h2&gt;
&lt;p&gt;If you disabled alert sending in the new cluster:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disable rule evaluations in the old cluster.&lt;/li&gt;
&lt;li&gt;Enable them in the new cluster by removing the override you previously set.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&#34;admonition admonition-tip&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Tip&lt;/p&gt;&lt;p&gt;Complete these actions in quick succession to prevent duplicate alerts.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;stop-writing-to-the-old-cluster&#34;&gt;Stop writing to the old cluster&lt;/h2&gt;
&lt;p&gt;Reconfigure write clients to only send data to the new cluster.&lt;/p&gt;
&lt;h2 id=&#34;decommission-the-old-cluster&#34;&gt;Decommission the old cluster&lt;/h2&gt;
&lt;p&gt;After the new cluster is fully operational, decommission the old cluster.
For example, if you’re using Helm, run the following 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;sh&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-sh&#34;&gt;helm uninstall &amp;lt;OLD_RELEASE_NAME&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Your system runs entirely with ingest storage architecture.&lt;/p&gt;
&lt;h2 id=&#34;scale-down-compactors-in-the-new-cluster&#34;&gt;Scale down compactors in the new cluster&lt;/h2&gt;
&lt;p&gt;After the migration is complete and the old cluster is decommissioned, reduce the number of compactor replicas in the new cluster to your normal steady-state configuration. This lowers resource use after the temporary load from the dual-cluster operation is gone.&lt;/p&gt;
]]></content><description>&lt;h1 id="migrate-from-classic-to-ingest-storage-architecture">Migrate from classic to ingest storage architecture&lt;/h1>
&lt;p>Migrate from a Grafana Mimir cluster running with classic architecture to one running with ingest storage architecture. This process allows you to migrate without downtime by temporarily running two clusters in parallel and duplicating writes. For background on the different architectures, refer to
&lt;a href="/docs/mimir/v3.1.x/get-started/about-grafana-mimir-architecture/">Grafana Mimir architecture&lt;/a>.&lt;/p></description></item></channel></rss>