<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pyroscope architecture on Grafana Labs</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/</link><description>Recent content in Pyroscope architecture on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/index.xml" rel="self" type="application/rss+xml"/><item><title>About the Pyroscope architecture</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/about-grafana-pyroscope-architecture/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/about-grafana-pyroscope-architecture/</guid><content><![CDATA[&lt;h1 id=&#34;about-the-pyroscope-architecture&#34;&gt;About the Pyroscope architecture&lt;/h1&gt;
&lt;p&gt;Pyroscope has a microservices-based architecture.
The system has multiple horizontally scalable microservices that can run separately and in parallel.
Pyroscope microservices are called components.&lt;/p&gt;
&lt;p&gt;Pyroscope&amp;rsquo;s design compiles the code for all components into a single binary.
The &lt;code&gt;-target&lt;/code&gt; parameter controls which component(s) that single binary will behave as. For those looking for a simple way to get started, Pyroscope can also be run in &lt;a href=&#34;../deployment-modes/#monolithic-mode&#34;&gt;monolithic mode&lt;/a&gt;, with all components running simultaneously in one process.
For more information, refer to &lt;a href=&#34;../deployment-modes/&#34;&gt;Deployment modes&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pyroscope-components&#34;&gt;Pyroscope components&lt;/h2&gt;
&lt;p&gt;Most components are stateless and do not require any data persisted between process restarts. Some components are stateful and rely on non-volatile storage to prevent data loss between process restarts. For details about each component, see its page in &lt;a href=&#34;../components/&#34;&gt;Components&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;the-write-path&#34;&gt;The write path&lt;/h3&gt;
&lt;p align=&#34;center&#34;&gt;
  &lt;img alt=&#34;Architecture of Pyroscope&#39;s write path&#34; width=&#34;200px&#34; src=&#34;https://mermaid.ink/svg/pako:eNqNkT1PwzAQhv9K5C6t1DY0hrT1wIBgZgCJoeng2OfE4MSRfaFUVf47dkoLI9vd896H7_WJCCuBMKKMPYiaO0xeH4o2SXoPbrp7cxrB72fJYnGfSO3R6bJH62LFn3SUdVuBRxi1SzwK1kckbNNxcSk-M-vH5Cqd2XT3XL6DwMQHBPtZpB6PBsZHJUobwyZqq-Zhv_0ANqGU_sSLg5ZYs6z7-m0KS_7bQuakAddwLYMjpziiIFhDAwVhIZSgeG-wIEU7hFIeTn85toIwdD3MSd9JjvCoeeV4Q5jixl_pk9ThmCs0lksI6YngsYv2V8HMMFLYVukq8t6ZgGvEzrM0jfKy0lj35TK4lXot41_Vn9s8zbN8wzMK-ZryO0qlKFfbjcpuV0qub1YZJ8MwfAN3mqSC&#34; /&gt;
  &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Ingesters receive incoming profiles from the distributors.
Each push request belongs to a tenant, and the ingester appends the received profiles to the specific per-tenant Pyroscope database that is stored on the local disk.&lt;/p&gt;
&lt;p&gt;The per-tenant Pyroscope database is lazily created in each ingester as soon as the first profiles are received for that tenant.&lt;/p&gt;
&lt;p&gt;The in-memory profiles are periodically flushed to disk and new block is created.&lt;/p&gt;
&lt;p&gt;For more information, refer to &lt;a href=&#34;../components/ingester/&#34;&gt;Ingester&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;series-sharding-and-replication&#34;&gt;Series sharding and replication&lt;/h4&gt;
&lt;p&gt;By default, each profile series is replicated to three ingesters, and each ingester writes its own block to the long-term storage. The &lt;a href=&#34;../components/compactor/&#34;&gt;Compactor&lt;/a&gt; merges blocks from multiple ingesters into a single block, and removes duplicate samples. Blocks compaction significantly reduces storage utilization.&lt;/p&gt;
&lt;h3 id=&#34;the-read-path&#34;&gt;The read path&lt;/h3&gt;
&lt;p align=&#34;center&#34;&gt;
  &lt;img alt=&#34;Architecture of Pyroscope&#39;s read path&#34; width=&#34;400px&#34; src=&#34;https://mermaid.ink/svg/pako:eNqNkT1PwzAQhv9K5C6t1DQ0gX54YEAwIwFb08G1z4nBiYN9pkRV_jt2gQJi6XZ-7rmTXt-BcCOAUCK12fOaWUyebso2SbwDO948ABNuO0nS9Dp59WD7VFrTIrQiOn_JL8nxGoTXYL8tBfactmorcPifOzQW0ooh7Fl_JMZFx7jx5n73DBw_le0kUoe9hmOARCqt6Uiu5dShNS9AR0VRfNXpXgmsad69_wwZd_YImZIGbMOUCL93iCtKgjU0UBIaSgGSeY0lKdshqMyjeexbTihaD1PiOxHS3CpWWdYQKpl2J3onVAhzgtowAeF5INh38VSVchhWctNKVUXurQ64RuwczbLYnlUKa7-bcdNkTol41_ptvcgW-WLF8gIWy4JdFYXgu_l6JfPLuRTLi3nOyDAMHzzctK0&#34; /&gt;
  &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Queries coming into Pyroscope arrive at &lt;a href=&#34;../components/query-frontend/&#34;&gt;query-frontend&lt;/a&gt; component which is responsible for accelerating queries and dispatching them to the &lt;a href=&#34;../components/query-scheduler/&#34;&gt;query-scheduler&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;../components/query-scheduler/&#34;&gt;query-scheduler&lt;/a&gt; maintains a queue of queries and ensures that each tenant&amp;rsquo;s queries are fairly executed.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;../components/querier/&#34;&gt;queriers&lt;/a&gt; act as workers, pulling queries from the queue in the query-scheduler. The queriers connect to the ingesters to fetch all the data needed to execute a query. For more information about how the query is executed, refer to &lt;a href=&#34;../components/querier/&#34;&gt;querier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Depending on the time window selected, the querier involves &lt;a href=&#34;../components/ingester/&#34;&gt;ingesters&lt;/a&gt; for recent data and &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateways&lt;/a&gt; for data from long-term storage.&lt;/p&gt;
&lt;h2 id=&#34;long-term-storage&#34;&gt;Long-term storage&lt;/h2&gt;
&lt;p&gt;The Pyroscope storage format is described in detail in on the &lt;a href=&#34;../block-format/&#34;&gt;block format page&lt;/a&gt;.
The Pyroscope storage format stores each tenant&amp;rsquo;s profiles into their own on-disk block. Each on-disk block directory contains an index file, a file containing metadata, and the Parquet tables.&lt;/p&gt;
&lt;p&gt;Pyroscope requires any of the following object stores for the block files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/s3&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Amazon S3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Google Cloud Storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://azure.microsoft.com/en-us/services/storage/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Microsoft Azure Storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.openstack.org/wiki/Swift&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenStack Swift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Local Filesystem (single node only)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information, refer to 
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/configure-server/storage/configure-object-storage-backend/&#34;&gt;configure object storage&lt;/a&gt; and 
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/configure-server/storage/configure-disk-storage/&#34;&gt;configure disk storage&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="about-the-pyroscope-architecture">About the Pyroscope architecture&lt;/h1>
&lt;p>Pyroscope has a microservices-based architecture.
The system has multiple horizontally scalable microservices that can run separately and in parallel.
Pyroscope microservices are called components.&lt;/p></description></item><item><title>Pyroscope deployment modes</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/deployment-modes/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/deployment-modes/</guid><content><![CDATA[&lt;h1 id=&#34;pyroscope-deployment-modes&#34;&gt;Pyroscope deployment modes&lt;/h1&gt;
&lt;p&gt;You can deploy Pyroscope in one of two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monolithic mode: In this mode all components run in a single process and is meant to be used when you &lt;em&gt;only need one pyroscope instance&lt;/em&gt; as multiple instances will not share information with each other&lt;/li&gt;
&lt;li&gt;Microservices mode: In this mode in this mode as you scale out the number of instances, they will share a singular backend for storage and querying&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The deployment mode is determined by the &lt;code&gt;-target&lt;/code&gt; parameter, which you can set via CLI flag or YAML configuration.&lt;/p&gt;
&lt;h2 id=&#34;monolithic-mode&#34;&gt;Monolithic mode&lt;/h2&gt;
&lt;p&gt;The monolithic mode runs all required components in a single process and is the default mode of operation, which you can set by specifying &lt;code&gt;-target=all&lt;/code&gt;. Monolithic mode is the simplest way to deploy Pyroscope and is useful if you want to get started quickly or want to work with Pyroscope in a development environment. To see the list of components that run when &lt;code&gt;-target&lt;/code&gt; is set to &lt;code&gt;all&lt;/code&gt;, run Pyroscope with the &lt;code&gt;-modules&lt;/code&gt; flag:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;./pyroscope -modules&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;monolithic-mode.svg&#34;
  alt=&#34;Pyroscope&amp;rsquo;s monolithic mode&#34;/&gt;&lt;/p&gt;
&lt;!--
Monolithic mode can be horizontally scaled out by deploying multiple Pyroscope binaries with `-target=all`. This approach provides high-availability and increased scale without the configuration complexity of the full [microservices deployment](#microservices-mode).

[//]: # &#34;Diagram source at https://docs.google.com/presentation/d/1C1fl0pH8wmKZe8gXo-VwmUuLvGiPmADfvey15FSkWpE/edit#slide=id.g11658e7e4c6_1_20&#34;

![Pyroscope&#39;s horizontally scaled monolithic mode](scaled-monolithic-mode.svg)
 --&gt;
&lt;h2 id=&#34;microservices-mode&#34;&gt;Microservices mode&lt;/h2&gt;
&lt;p&gt;In microservices mode, components are deployed in distinct processes. Scaling is per component, which allows for greater flexibility in scaling and more granular failure domains. Microservices mode is the preferred method for a production deployment, but it is also the most complex.&lt;/p&gt;
&lt;p&gt;In microservices mode, each Pyroscope process is invoked with its &lt;code&gt;-target&lt;/code&gt; parameter set to a specific Pyroscope component (for example, &lt;code&gt;-target=ingester&lt;/code&gt; or &lt;code&gt;-target=distributor&lt;/code&gt;). To get a working Pyroscope instance, you must deploy every required component. For more information about each of the Pyroscope components, refer to &lt;a href=&#34;../&#34;&gt;Architecture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in deploying Pyroscope in microservices mode, we recommend that you use &lt;a href=&#34;https://kubernetes.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Kubernetes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;microservices-mode.svg&#34;
  alt=&#34;Pyroscope&amp;rsquo;s microservices mode&#34;/&gt;&lt;/p&gt;
]]></content><description>&lt;h1 id="pyroscope-deployment-modes">Pyroscope deployment modes&lt;/h1>
&lt;p>You can deploy Pyroscope in one of two modes:&lt;/p>
&lt;ul>
&lt;li>Monolithic mode: In this mode all components run in a single process and is meant to be used when you &lt;em>only need one pyroscope instance&lt;/em> as multiple instances will not share information with each other&lt;/li>
&lt;li>Microservices mode: In this mode in this mode as you scale out the number of instances, they will share a singular backend for storage and querying&lt;/li>
&lt;/ul>
&lt;p>The deployment mode is determined by the &lt;code>-target&lt;/code> parameter, which you can set via CLI flag or YAML configuration.&lt;/p></description></item><item><title>Pyroscope components</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/</guid><content><![CDATA[&lt;h1 id=&#34;pyroscope-components&#34;&gt;Pyroscope components&lt;/h1&gt;
&lt;p&gt;Pyroscope includes a set of components that interact to form a cluster.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/compactor/&#34;&gt;Compactor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/distributor/&#34;&gt;Distributor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/ingester/&#34;&gt;Ingester&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/querier/&#34;&gt;Querier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/store-gateway/&#34;&gt;Store-gateway&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/query-frontend/&#34;&gt;Query-frontend&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/query-scheduler/&#34;&gt;Query-scheduler&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
]]></content><description>&lt;h1 id="pyroscope-components">Pyroscope components&lt;/h1>
&lt;p>Pyroscope includes a set of components that interact to form a cluster.&lt;/p>
&lt;ul>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/compactor/">Compactor&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/distributor/">Distributor&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/ingester/">Ingester&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/querier/">Querier&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/store-gateway/">Store-gateway&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/query-frontend/">Query-frontend&lt;/a>&lt;/li>&lt;li>
&lt;a href="/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/components/query-scheduler/">Query-scheduler&lt;/a>&lt;/li>&lt;/ul></description></item><item><title>Grafana Pyroscope bucket index</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/bucket-index/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/bucket-index/</guid><content><![CDATA[&lt;h1 id=&#34;grafana-pyroscope-bucket-index&#34;&gt;Grafana Pyroscope bucket index&lt;/h1&gt;
&lt;p&gt;The bucket index is a per-tenant file that contains the list of blocks and block deletion marks in the storage. The bucket index is stored in the backend object storage, is periodically updated by the compactor, and used by store-gateways to discover blocks in the storage.&lt;/p&gt;
&lt;h2 id=&#34;benefits&#34;&gt;Benefits&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateway&lt;/a&gt; must have an almost&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; up-to-date view of the storage bucket, in order to find the right blocks to look up at query time and to load a block.&lt;/p&gt;
&lt;p&gt;Because of this, they need to periodically scan the bucket to look for new blocks uploaded by ingesters or compactors, and blocks deleted (or marked for deletion) by compactors.&lt;/p&gt;
&lt;p&gt;When the bucket index is enabled, store-gateways periodically look up the per-tenant bucket index instead of scanning the bucket via &lt;code&gt;list objects&lt;/code&gt; operations.&lt;/p&gt;
&lt;p&gt;This provides the following benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reduced number of API calls to the object storage by store-gateway&lt;/li&gt;
&lt;li&gt;No &amp;ldquo;list objects&amp;rdquo; storage API calls performed by store-gateway&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;structure-of-the-index&#34;&gt;Structure of the index&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;bucket-index.json.gz&lt;/code&gt; contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;blocks&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
List of complete blocks of a tenant, including blocks marked for deletion. Partial blocks are excluded from the index.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;block_deletion_marks&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
List of block deletion marks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;updated_at&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
A Unix timestamp, with precision measured in seconds, displays the last time index was updated and written to the storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-it-gets-updated&#34;&gt;How it gets updated&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/compactor/&#34;&gt;compactor&lt;/a&gt; periodically scans the bucket and uploads an updated bucket index to the storage.
You can configure the frequency with which the bucket index is updated via &lt;code&gt;-compactor.cleanup-interval&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The use of the bucket index is optional, but the index is built and updated by the compactor even if &lt;code&gt;-blocks-storage.bucket-store.bucket-index.enabled=false&lt;/code&gt;.
This behavior ensures that the bucket index for any tenant exists and that query result consistency is guaranteed if a Grafana Pyroscope cluster operator enables the bucket index in a live cluster.
The overhead introduced by keeping the bucket index updated is not significant.&lt;/p&gt;
&lt;h2 id=&#34;how-its-used-by-the-store-gateway&#34;&gt;How it&amp;rsquo;s used by the store-gateway&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;../components/store-gateway/&#34;&gt;store-gateway&lt;/a&gt;, at startup and periodically, fetches the bucket index for each tenant that belongs to its shard, and uses it as the source of truth for the blocks and deletion marks in the storage. This removes the need to periodically scan the bucket to discover blocks belonging to its shard.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Ingesters regularly add new blocks to the bucket as they offload data to long-term storage,
and compactors subsequently compact these blocks and mark the original blocks for deletion.
Actual deletion happens after the delay value that is associated with the parameter &lt;code&gt;-compactor.deletion-delay&lt;/code&gt;.
An attempt to fetch a deleted block will lead to failure of the query.
Therefore, in this context, an &lt;em&gt;almost up-to-date&lt;/em&gt; view is a view that’s outdated by less than the value of &lt;code&gt;-compactor.deletion-delay&lt;/code&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="grafana-pyroscope-bucket-index">Grafana Pyroscope bucket index&lt;/h1>
&lt;p>The bucket index is a per-tenant file that contains the list of blocks and block deletion marks in the storage. The bucket index is stored in the backend object storage, is periodically updated by the compactor, and used by store-gateways to discover blocks in the storage.&lt;/p></description></item><item><title>Pyroscope Block format</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/block-format/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/block-format/</guid><content><![CDATA[&lt;h1 id=&#34;pyroscope-block-format&#34;&gt;Pyroscope Block format&lt;/h1&gt;
&lt;p&gt;This document describes how Pyroscope stores the data in its blocks. Each
block belongs to a single tenant and is identified by a unique &lt;a href=&#34;https://github.com/ulid/spec&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;ULID&lt;/a&gt;. Within
the block there are multiple files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A metadata file &lt;code&gt;meta.json&lt;/code&gt;, which contains information about what the block
contains, like the time range of the profiling data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;a href=&#34;https://ganeshvernekar.com/blog/prometheus-tsdb-persistent-block-and-its-index/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;TSDB index&lt;/a&gt; &lt;code&gt;index.tsdb&lt;/code&gt; mapping the external labels to the profiles
stored in the profiles table.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;profiles.parquet&lt;/code&gt; &lt;a href=&#34;https://parquet.apache.org/docs/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;parquet&lt;/a&gt; table that contains profiles.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;symbols.symdb&lt;/code&gt; that contains symbolic information for the profiles stored in the block.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;data-model&#34;&gt;Data model&lt;/h2&gt;
&lt;p&gt;The data model within the block is fairly aligned to Google&amp;rsquo;s &lt;a href=&#34;https://github.com/google/pprof/blob/main/proto/profile.proto&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;proto definition&lt;/a&gt; for the pprof wire format.&lt;/p&gt;
&lt;p&gt;Profile series labels contain additional information gathered at ingestion time and can
be used to select certain profiles. They are comparable to Prometheus/Loki labels
and typical label names are &lt;code&gt;namespace&lt;/code&gt; and &lt;code&gt;pod&lt;/code&gt; to describe which workload the profiles
are coming from.&lt;/p&gt;
&lt;p&gt;Each profile ingested will be added into a new row in the profile table. If
there are entries missing in the tables for the different models they are also
inserted.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;model.svg&#34;
  alt=&#34;Data model of Pyroscope blocks&#34;/&gt;&lt;/p&gt;
]]></content><description>&lt;h1 id="pyroscope-block-format">Pyroscope Block format&lt;/h1>
&lt;p>This document describes how Pyroscope stores the data in its blocks. Each
block belongs to a single tenant and is identified by a unique &lt;a href="https://github.com/ulid/spec" target="_blank" rel="noopener noreferrer">ULID&lt;/a>. Within
the block there are multiple files:&lt;/p></description></item><item><title>Pyroscope hash rings</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/hash-ring/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/hash-ring/</guid><content><![CDATA[&lt;h1 id=&#34;pyroscope-hash-rings&#34;&gt;Pyroscope hash rings&lt;/h1&gt;
&lt;p&gt;Hash rings are a distributed &lt;a href=&#34;https://en.wikipedia.org/wiki/Consistent_hashing&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;consistent hashing scheme&lt;/a&gt; and are widely used by Pyroscope for sharding and replication.&lt;/p&gt;
&lt;h2 id=&#34;how-the-hash-ring-works-in-pyroscope&#34;&gt;How the hash ring works in Pyroscope&lt;/h2&gt;
&lt;p&gt;The hash ring in Pyroscope is used to share work across several replicas of a component in a consistent way, so that any other component can decide which address to talk to.
The workload or data to share is hashed first and the result of the hashing is used to find which ring member owns it.&lt;/p&gt;
&lt;p&gt;Pyroscope uses the &lt;code&gt;fnv32a&lt;/code&gt; hash function, which returns 32-bit unsigned integers so its value can be between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;(2^32)-1&lt;/code&gt;, inclusive.
This value is called &lt;em&gt;token&lt;/em&gt; and used as the ID of the data.
The token determines the location on the hash ring deterministically.
This allows independent determination of what instance of Pyroscope is the authoritative owner of any specific data.&lt;/p&gt;
&lt;p&gt;For example, profiles are sharded across &lt;a href=&#34;../components/ingester/&#34;&gt;ingesters&lt;/a&gt;.
The token of a given profile is computed by hashing all of the profile’s labels and the tenant ID: the result of which is an unsigned 32-bit integer within the space of the tokens.
The ingester that owns that series is the instance that owns the range of the tokens, including the profile token.&lt;/p&gt;
&lt;p&gt;To divide up set of possible tokens (&lt;code&gt;2^32&lt;/code&gt;) across the available instances within the cluster, all of the running instances of a given Pyroscope component, such as the ingesters, join a hash ring.
The hash ring is a data structure that splits the space of the tokens into multiple ranges, and assigns each range to a given Pyroscope ring member.&lt;/p&gt;
&lt;p&gt;Upon startup, an instance generates random token values, and it registers them into the ring.
The values that each instance registers determine which instance owns a given token.
A token is owned by the instance that registered the smallest value that is higher than the token being looked up (by wrapping around zero when it reaches &lt;code&gt;(2^32)-1)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;To replicate the data across multiple instances, Pyroscope finds the replicas by starting from the authoritative owner of the data and walking the ring clockwise.
Data is replicated to the next instances found while walking the ring.&lt;/p&gt;
&lt;h3 id=&#34;a-practical-example&#34;&gt;A practical example&lt;/h3&gt;
&lt;p&gt;To better understand how it works, take four ingesters and a tokens space between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;9&lt;/code&gt; as an example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ingester #1 is registered in the ring with the token &lt;code&gt;2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #2 is registered in the ring with the token &lt;code&gt;4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #3 is registered in the ring with the token &lt;code&gt;6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ingester #4 is registered in the ring with the token &lt;code&gt;9&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pyroscope receives an incoming performance profile with labels &lt;code&gt;{__name__=&amp;quot;process_cpu&amp;quot;, instance=&amp;quot;1.1.1.1&amp;quot;}&lt;/code&gt;.
It hashes the profile’s labels, and the result of the hashing function is the token &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To find which ingester owns token &lt;code&gt;3&lt;/code&gt;, Pyroscope looks up the token &lt;code&gt;3&lt;/code&gt; in the ring and finds the ingester that is registered with the smallest token larger than &lt;code&gt;3&lt;/code&gt;.
The ingester #2, which is registered with token &lt;code&gt;4&lt;/code&gt;, is the authoritative owner of the profile &lt;code&gt;{__name__=&amp;quot;process_cpu&amp;quot;,instance=&amp;quot;1.1.1.1&amp;quot;}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;hash-ring-without-replication.png&#34;
  alt=&#34;Hash ring without replication&#34;/&gt;&lt;/p&gt;
&lt;p&gt;With replication set to &lt;code&gt;3&lt;/code&gt;, Pyroscope replicates each profile to three ingesters.
After finding the authoritative owner of the profile, Pyroscope continues to walk the ring clockwise to find the remaining two instances where the profile should be replicated.
In the example that follows, the profile is replicated to the instances of &lt;code&gt;Ingester #3&lt;/code&gt; and &lt;code&gt;Ingester #4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;hash-ring-with-replication.png&#34;
  alt=&#34;Hash ring with replication&#34;/&gt;&lt;/p&gt;
&lt;h3 id=&#34;consistent-hashing&#34;&gt;Consistent hashing&lt;/h3&gt;
&lt;p&gt;The hash ring guarantees the property known as consistent hashing.&lt;/p&gt;
&lt;p&gt;When an instance is added or removed from the ring, consistent hashing minimizes the number of tokens that are moved from one instance to another.
On average, the number of tokens that need to move to a different instance is only &lt;code&gt;n/m&lt;/code&gt;, where &lt;code&gt;n&lt;/code&gt; is the total number of tokens (32-bit unsigned integer) and &lt;code&gt;m&lt;/code&gt; is the number of instances that are registered in the ring.&lt;/p&gt;
&lt;h2 id=&#34;components-that-use-the-hash-ring&#34;&gt;Components that use the hash ring&lt;/h2&gt;
&lt;p&gt;There are several Pyroscope components that need a hash ring.
Each of the following components builds an independent hash ring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../components/ingester/&#34;&gt;Ingesters&lt;/a&gt; shard and replicate series.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../components/distributor/&#34;&gt;Distributors&lt;/a&gt; enforce rate limits.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-the-hash-ring-is-shared-between-pyroscope-instances&#34;&gt;How the hash ring is shared between Pyroscope instances&lt;/h2&gt;
&lt;p&gt;Hash ring data structures need to be shared between Pyroscope instances.
To propagate changes to the hash ring, Pyroscope uses a key-value store.
The key-value store is required and can be configured independently for the hash rings of different components.&lt;/p&gt;
&lt;p&gt;For more information, see the &lt;a href=&#34;../memberlist-and-the-gossip-protocol/&#34;&gt;memberlist documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;features-that-are-built-using-the-hash-ring&#34;&gt;Features that are built using the hash ring&lt;/h2&gt;
&lt;p&gt;Pyroscope primarily uses the hash ring for sharding and replication.
Features that are built using the hash ring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Service discovery&lt;/strong&gt;: Instances can discover each other looking up who is registered in the ring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heartbeats&lt;/strong&gt;: Instances periodically send a heartbeat to the ring to signal they&amp;rsquo;re up and running. An instance is considered unhealthy if it misses the heartbeat for some period of time.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="pyroscope-hash-rings">Pyroscope hash rings&lt;/h1>
&lt;p>Hash rings are a distributed &lt;a href="https://en.wikipedia.org/wiki/Consistent_hashing" target="_blank" rel="noopener noreferrer">consistent hashing scheme&lt;/a> and are widely used by Pyroscope for sharding and replication.&lt;/p>
&lt;h2 id="how-the-hash-ring-works-in-pyroscope">How the hash ring works in Pyroscope&lt;/h2>
&lt;p>The hash ring in Pyroscope is used to share work across several replicas of a component in a consistent way, so that any other component can decide which address to talk to.
The workload or data to share is hashed first and the result of the hashing is used to find which ring member owns it.&lt;/p></description></item><item><title>Pyroscope memberlist and gossip protocol</title><link>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/memberlist-and-the-gossip-protocol/</link><pubDate>Wed, 08 Apr 2026 14:38:28 +0000</pubDate><guid>https://grafana.com/docs/pyroscope/v1.18.x/reference-pyroscope-architecture/memberlist-and-the-gossip-protocol/</guid><content><![CDATA[&lt;h1 id=&#34;pyroscope-memberlist-and-gossip-protocol&#34;&gt;Pyroscope memberlist and gossip protocol&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/hashicorp/memberlist&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Memberlist&lt;/a&gt; is a Go library that manages cluster membership, node failure detection, and message passing using a gossip-based protocol.
Memberlist is eventually consistent and network partitions are partially tolerated by attempting to communicate to potentially dead nodes through multiple routes.&lt;/p&gt;
&lt;p&gt;Pyroscope uses memberlist to implement the &lt;a href=&#34;../hash-ring/&#34;&gt;hash ring&lt;/a&gt; data structures between instances.&lt;/p&gt;
&lt;p&gt;Each instance maintains a copy of the hash rings.
Each Pyroscope instance updates a hash ring locally and uses memberlist to propagate the changes to other instances.
Updates generated locally and updates received from other instances are merged together to form the current state of the ring on the instance.&lt;/p&gt;
&lt;p&gt;To configure memberlist, refer to &lt;a href=&#34;../../configure-server/configuring-memberlist/&#34;&gt;configuring memberlist&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-memberlist-propagates-hash-ring-changes&#34;&gt;How memberlist propagates hash ring changes&lt;/h2&gt;
&lt;p&gt;When using a memberlist-based KV store, every Pyroscope instance propagates the hash ring data structures to other instances using the following techniques:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Propagating only the differences introduced in recent changes.&lt;/li&gt;
&lt;li&gt;Propagating the full hash ring data structure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every &lt;code&gt;-memberlist.gossip-interval&lt;/code&gt; an instance randomly selects a subset of all Pyroscope cluster instances configured by &lt;code&gt;-memberlist.gossip-nodes&lt;/code&gt; and sends the latest changes to the selected instances.
This operation is performed frequently and it&amp;rsquo;s the primary technique used to propagate changes.&lt;/p&gt;
&lt;p&gt;In addition, every &lt;code&gt;-memberlist.pullpush-interval&lt;/code&gt; an instance randomly selects another instance in the Pyroscope cluster and transfers the full content of the KV store, including all hash rings (unless &lt;code&gt;-memberlist.pullpush-interval&lt;/code&gt; is zero, which disables this behavior).
After this operation is complete, the two instances have the same content as the KV store.
This operation is computationally more expensive, and as a result, it&amp;rsquo;s performed less frequently. The operation ensures that the hash rings periodically reconcile to a common state.&lt;/p&gt;
]]></content><description>&lt;h1 id="pyroscope-memberlist-and-gossip-protocol">Pyroscope memberlist and gossip protocol&lt;/h1>
&lt;p>&lt;a href="https://github.com/hashicorp/memberlist" target="_blank" rel="noopener noreferrer">Memberlist&lt;/a> is a Go library that manages cluster membership, node failure detection, and message passing using a gossip-based protocol.
Memberlist is eventually consistent and network partitions are partially tolerated by attempting to communicate to potentially dead nodes through multiple routes.&lt;/p></description></item></channel></rss>