There are a couple of things to unwrap here.

First, rate vs irate. Neither the linked question, nor the blog post address this (but Eitan's answer does touch on it). The difference is that rate estimates the average rate over the requested range (1 minute, in your case) while irate computes the rate based on the last 2 samples only. Leaving aside the "estimate" part (see this answer if you're curious) the practical difference between the 2 is that rate will smooth out the result, whereas irate will return a sampling of CPU usage, which is more likely to show extremes in CPU usage but also more prone to aliasing.

E.g. if you look at Prometheus' CPU usage, you'll notice that it's at a somewhat constant baseline, with a spike every time a large rule group is evaluated. Given a time range that was at least as long as Prometheus' evaluation interval, if you used rate you'd get a more or less constant CPU usage over time (i.e. a flat line). With irate (assuming a scrape interval of 5s) you'd get one of 2 things:

  1. if your resolution (i.e. step) was not aligned with Prometheus' evaluation interval (e.g. the resolution was 1m and the evaluation interval was 13s) you'd get a random sampling of CPU usage and would hopefully see values close to both the highest and lowest CPU usage over time on a graph;
  2. if your resolution was aligned with Prometheus' evaluation interval (e.g. 1m resolution and 15s evaluation interval) then you'd either see the baseline CPU usage everywhere (because you happen to look at 5s intervals set 1 minute apart, when no rule evaluation happens) or the peak CPU usage everywhere (because you happen to look at 5s intervals 1 minute apart that each cover a rule evaluation).

Regarding the second point, the apparent confusion over what the node_cpu_seconds_total metric represents, it is a counter. Meaning it's a number that increments continuously and essentially measures the amount of time the CPU was idle since the exporter started. The absolute value is not all that useful (as it depends on when the exporter started and will drop to 0 on every restart). What's interesting about it is by how much it increased over a period of time: from that you can compute for a given period of time a rate of increase per second (average, with rate; instant, with irate) or an absolute increase (with increase). So both rate(node_cpu_seconds_total{mode="idle"}[1m]) and irate(node_cpu_seconds_total{mode="idle"}[1m]) will give you a ratio (between 0.0 and 1.0) of how much the CPU was idle (over the past minute, and respectively between the last 2 samples).

Answer from Alin Sînpălean on Stack Overflow
🌐
Medium
medium.com › @kavyaprathyusha › rate-vs-irate-in-promql-a172e3d9c38f
rate() vs irate() in promQL - by Kavya Prathyusha Chekka
August 16, 2021 - rate() is generally used when graphing the slow moving counters. While irate() is used when graphing the high volatile counters. Hope this post helps someone! :) Prometheus · Alerting · Promql · 14 followers · ·34 following · Help · Status ...
🌐
Chris's Wiki
utcc.utoronto.ca › ~cks › space › blog › sysadmin › PrometheusRateVsIrate
rate() versus irate() in Prometheus (and Grafana)
November 5, 2018 - In particular, it's often said ... To explain that, I need to start with what these two functions do and go on to the corollaries. rate() is the simpler function to describe....
Discussions

Why is CPU utilization calculated using irate or rate in Prometheus? - Stack Overflow
I know that CPU utilization is given by the percentage of non-idle time over the total time of CPU. In Prometheus, rate or irate functions calculate the rate of change in a vector array. People often calculate the CPU utilisation by the following PromQL expression: More on stackoverflow.com
🌐 stackoverflow.com
irate() Vs rate() Functions in Prometheus

Let’s say you have a counter with these values observed at 1m intervals:

0
60
120
600
720
780

Now rate over 5m will be:

(780-0)/5/60 = 2.6/sec

And irate over 5m will be (only last two data points are used which happen to be only 1m apart)

(780-720)/1/60 = 1/sec

Increasing the resolution does not affect the irate function because the last two observed values do not change when you look further back.

More on reddit.com
🌐 r/PrometheusMonitoring
9
12
February 4, 2020
Rate and irate display very different values
Hello, I’ve got the two following sentences on two different graphs: rate(node_disk_bytes_read{job=“node_exporter”}[5m]) irate(node_disk_bytes_read{job=“node_exporter”}[5m]) The unit is bytes. As you can see in the attached image, on one graph the maximum reaches almost 12MiB, whereas ... More on community.grafana.com
🌐 community.grafana.com
4
1
April 4, 2018
rate/sum confusion
What you're confusing is columns and rows. If you imagine each metric name like a column, and the label values as rows. If you want to add up a row, you use the + operator, if you want to add up a column, you use sum(). So if you want to sum up all the interfaces on a single instance, you do something like this: sum without (instance,name) ( rate(ifHCOutOctets{instance="10.1.2.3",job="Firewalls",name="Firewall-1"}[30s]) ) * 8 Note that I don't include the ifIndex label filter. This means all labels will match. If you want to match multiple labels at a time, you will need to use a regular expression match. Something like ifIndex=~"(500010723|500010724)". EDIT: An example of a valid use of the + operator would be something like this: sum by (name) (rate(ifHCOutOctets[1m])) + sum by (name) (rate(ifHCInOctets[1m])) Note that we're adding up two columns, in and out octets. More on reddit.com
🌐 r/PrometheusMonitoring
6
1
October 17, 2019
People also ask

Are there approaches for capturing spikes with PromQL?
Yes, max_over_time() can be used with rate() to capture spikes. For example, max_over_time(rate(http_requests_total[5m])[1h:]) will show the maximum rate observed in 5-minute windows over the last hour.
🌐
last9.io
last9.io › blog › prometheus-rate-function
Prometheus Rate Function: A Practical Guide to Using It | Last9
How do you calculate request rates using the Prometheus rate function?
To calculate request rates, use a query like rate(http_requests_total[5m]). This will give the per-second rate of requests over the last 5 minutes. These rates can be summed or grouped as needed, e.g., sum(rate(http_requests_total[5m])) for the total request rate across all instances.
🌐
last9.io
last9.io › blog › prometheus-rate-function
Prometheus Rate Function: A Practical Guide to Using It | Last9
How does the Prometheus rate() function differ from increase()?
While rate() calculates the per-second average rate of increase, increase() calculates the total increase in the counter's value over the time range. rate() is generally more useful for ongoing monitoring, while increase() can help understand total change over a specific period.
🌐
last9.io
last9.io › blog › prometheus-rate-function
Prometheus Rate Function: A Practical Guide to Using It | Last9
🌐
Last9
last9.io › blog › prometheus-rate-function
Prometheus Rate Function: A Practical Guide to Using It | Last9
June 15, 2026 - The key difference is that rate() averages across your entire time range, providing stability at the cost of potentially masking brief spikes, while irate() is more responsive but produces noisier visualizations.
🌐
MetricFire
metricfire.com › blog › understanding-the-prometheus-rate-function
How the Prometheus rate() function works | MetricFire
March 12, 2026 - The nice thing about the rate() function is that it considers all data points, not just the first and last ones. Another function, irate, uses only the first and last data points.
Top answer
1 of 2
25

There are a couple of things to unwrap here.

First, rate vs irate. Neither the linked question, nor the blog post address this (but Eitan's answer does touch on it). The difference is that rate estimates the average rate over the requested range (1 minute, in your case) while irate computes the rate based on the last 2 samples only. Leaving aside the "estimate" part (see this answer if you're curious) the practical difference between the 2 is that rate will smooth out the result, whereas irate will return a sampling of CPU usage, which is more likely to show extremes in CPU usage but also more prone to aliasing.

E.g. if you look at Prometheus' CPU usage, you'll notice that it's at a somewhat constant baseline, with a spike every time a large rule group is evaluated. Given a time range that was at least as long as Prometheus' evaluation interval, if you used rate you'd get a more or less constant CPU usage over time (i.e. a flat line). With irate (assuming a scrape interval of 5s) you'd get one of 2 things:

  1. if your resolution (i.e. step) was not aligned with Prometheus' evaluation interval (e.g. the resolution was 1m and the evaluation interval was 13s) you'd get a random sampling of CPU usage and would hopefully see values close to both the highest and lowest CPU usage over time on a graph;
  2. if your resolution was aligned with Prometheus' evaluation interval (e.g. 1m resolution and 15s evaluation interval) then you'd either see the baseline CPU usage everywhere (because you happen to look at 5s intervals set 1 minute apart, when no rule evaluation happens) or the peak CPU usage everywhere (because you happen to look at 5s intervals 1 minute apart that each cover a rule evaluation).

Regarding the second point, the apparent confusion over what the node_cpu_seconds_total metric represents, it is a counter. Meaning it's a number that increments continuously and essentially measures the amount of time the CPU was idle since the exporter started. The absolute value is not all that useful (as it depends on when the exporter started and will drop to 0 on every restart). What's interesting about it is by how much it increased over a period of time: from that you can compute for a given period of time a rate of increase per second (average, with rate; instant, with irate) or an absolute increase (with increase). So both rate(node_cpu_seconds_total{mode="idle"}[1m]) and irate(node_cpu_seconds_total{mode="idle"}[1m]) will give you a ratio (between 0.0 and 1.0) of how much the CPU was idle (over the past minute, and respectively between the last 2 samples).

2 of 2
0

Looks like this is already answered here: Prometheus - Convert cpu_user_seconds to CPU Usage %? Looking at the provided link in the answers: https://www.robustperception.io/understanding-machine-cpu-usage you can see the explanation. Personally, I think that irate in this context makes more sense, as it will show you the average on the last active points (vs. rate which will average the entire sampled timeslot).

🌐
Reddit
reddit.com › r/prometheusmonitoring › irate() vs rate() functions in prometheus
r/PrometheusMonitoring on Reddit: irate() Vs rate() Functions in Prometheus
February 4, 2020 -

Hi All,

I'm trying to understand how irate() & rate() functions work. Why does irate() produce a similar looking graph when the range / resolution is 24h or 5m ? While the difference in graph is clearly visible with rate() when using range as 24h (presents a smoothed out line) or 5m(more spikey).

In the below graph for irate() for 2 different resolutions the graph looks the same. As per prometheus docs irate() calculates the per second instant rate based on the last two data points. What does this mean if my range is 24h? Thank you.

https://preview.redd.it/08mc4pq2mye41.jpg?width=3206&format=pjpg&auto=webp&s=4aef0b681969c8b9831ec0f34310838511ea0350

Find elsewhere
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › functions
Query functions | Prometheus
irate should only be used when graphing volatile, fast-moving counters. Use rate for alerts and slow-moving counters, as brief changes in the rate can reset the FOR clause and graphs consisting entirely of rare spikes are hard to read.
🌐
Promlabs
promlabs.com › blog › 2021 › 01 › 29 › how-exactly-does-promql-calculate-rates
PromLabs | Blog - How Exactly Does PromQL Calculate Rates?
January 29, 2021 - Since irate() really only looks at the per-second increase between two samples, it does not do any of this extrapolation. Although counters normally only go up, they reset to 0 whenever a process that tracks them restarts. To not interpret these resets as actual negative rates, the counter-related functions have logic to detect and deal with those resets: when iterating over the samples under the provided time window, the functions check whether any sample has a lower value than the previous one, and interpret this situation as a counter reset.
🌐
Tech Annotation
techannotation.wordpress.com › 2021 › 07 › 19 › irate-vs-rate-whatre-they-telling-you
irate() vs rate() – What're they telling you? - Tech Annotation
July 22, 2021 - It depends on what you’re going to show and what you want to highlight. irate() is more susceptible to data variations, while rate() gives us an overall traffic trend of our application.
🌐
DevOps.dev
blog.devops.dev › prometheus-theory-rate-vs-irate-20e6243a3ab8
[Prometheus Theory] rate() vs. irate() | by - DevOps.dev
October 26, 2023 - The rate() function would average using the first and last data points, averaged over the query interval (1m); whereas the irate() function would average using the last two data points, averaged over the scrape interval (15s).
🌐
DevOpsil
devopsil.com › home › prometheus › promql queries you'll actually use in production
PromQL Queries You'll Actually Use in Production | DevOpsil
March 29, 2026 - Use irate() only when you need per-second instantaneous rates and are fine with noisier graphs.
🌐
Medium
medium.com › @bhupender.rawat4 › demystifying-prometheus-a-deep-dive-into-rate-and-irate-ce02745231fc
Demystifying Prometheus: A Deep Dive into rate() and irate() | by Bhupender Singh Rawat | Medium
May 7, 2025 - These two functions play a crucial role in analyzing application performance, troubleshooting issues, and defining alert conditions. Whether you're investigating latency spikes, error rates, or request throughput, knowing when and how to use rate() vs irate() can dramatically improve the accuracy of your monitoring and the reliability of your alerts.
🌐
PagerTree
pagertree.com › learn › prometheus › promeql › counter rates & increases
Counter Rates & Increases | PagerTree
rate() - "rate of increase" - calculates a per-second increase of a counter as averaged over a specified window. ... irate() - "instantaneous rate of increase" - calculates a per-second increase over the time window, only considering the last ...
🌐
Compile N Run
compilenrun.com › prometheus tutorial › promql (prometheus query language) › promql rate function
PromQL Rate Function | Compile N Run
The rate() function is a cornerstone of PromQL that transforms counter metrics into more actionable per-second rates. Key points to remember: ... Use rate() for visualization and general monitoring; consider irate() for alerting on sudden changes
🌐
Grafana
community.grafana.com › prometheus
Rate and irate display very different values - Prometheus - Grafana Labs Community Forums
April 4, 2018 - Hello, I’ve got the two following sentences on two different graphs: rate(node_disk_bytes_read{job=“node_exporter”}[5m]) irate(node_disk_bytes_read{job=“node_exporter”}[5m]) The unit is bytes. As you can see in the attached image, on one graph the maximum reaches almost 12MiB, whereas in the other it reaches about 650KiB.
🌐
Medium
valyala.medium.com › why-irate-from-prometheus-doesnt-capture-spikes-45f9896d7832
Why irate from Prometheus doesn't capture spikes | by Aliaksandr Valialkin | Medium
November 17, 2021 - But irate returns a sample of per-second rates for such counters. The returned sample may contain all the spikes, a part of spikes or it may miss all the spikes and capture random rates.
🌐
Medium
mohansaiteki.medium.com › manually-calculate-the-rate-irate-and-increase-functions-in-prometheus-7e755fff9897
Manually calculate the rate, irate, and increase functions in Prometheus
August 21, 2023 - starting value in timerange (v2) - next occurance value in timerange (v1) rate = --------------------------------------------------------------------------- starting time in timerange (t2) - next occurance time in timerange (t1) Here irate considers the starting value and next occurrence of the value in a given time range and divides that with no of seconds in between the values and it won’t consider the end value like the rate function.
🌐
pint
cloudflare.github.io › pint › checks › promql › rate.html
promql/rate | pint
Metrics passed to rate() and irate() are counters. Both functions only work with counters and, although any metric type can be passed to it and will return calculated value, using a non-counter will cause problems. This is because counters are only allowed to increase in value and any value ...
🌐
DoHost
dohost.us › home › 2025 › september › 27 › using promql functions: calculating rates and averages
Using PromQL Functions: Calculating Rates and Averages - DoHost
September 27, 2025 - When to Use `irate()`: Use `irate()` when you need to detect sudden changes or spikes in your metrics. Example Scenario: Detecting a sudden surge in error rates on your website. You can calculate averages over time using the `avg_over_time()` ...
🌐
Erhwenkuo
erhwenkuo.github.io › prometheus › promql › rates
rate 函數- 變化率
使用 irate() 函數上面的表達式則會出現一些短暫下降的圖形: · 除了計算每秒速率,你還可以使用 increase() 函數查詢指定時間範圍內的總增量,它基本上相當於速率乘以時間範圍選擇器中的秒數: · increase(demo_api_request_duration_seconds_count{job="demo"}[1h]) 比如上面表達式的結果和使用 rate() 函數計算的結果整體圖形趨勢都是一樣的,只是 Y 軸的數據不一樣而已,一個表示數量,一個表示百分比。 rate()、irate() 和 increase() 函數只能輸出非負值的結果,對於跟踪一個可以上升或下降的值的指標(如溫度、內存或磁盤空間),可以使用 delta() 和 deriv() 函數來代替。