In an ideal world (where your samples' timestamps are exactly on the second and your rule evaluation happens exactly on the second) rate(counter[1s]) would return exactly your ICH value and rate(counter[5s]) would return the average of that ICH and the previous 4. Except the ICH at second 1 is 0, not 1, because no one knows when your counter was zero: maybe it incremented right there, maybe it got incremented yesterday, and stayed at 1 since then. (This is the reason why you won't see an increase the first time a counter appears with a value of 1 -- because your code just created and incremented it.)

increase(counter[5s]) is exactly rate(counter[5s]) * 5 (and increase(counter[2s]) is exactly rate(counter[2s]) * 2).

Now what happens in the real world is that your samples are not collected exactly every second on the second and rule evaluation doesn't happen exactly on the second either. So if you have a bunch of samples that are (more or less) 1 second apart and you use Prometheus' rate(counter[1s]), you'll get no output. That's because what Prometheus does is it takes all the samples in the 1 second range [now() - 1s, now()] (which would be a single sample in the vast majority of cases), tries to compute a rate and fails.

If you query rate(counter[5s]) OTOH, Prometheus will pick all the samples in the range [now() - 5s, now] (5 samples, covering approximately 4 seconds on average, say [t1, v1], [t2, v2], [t3, v3], [t4, v4], [t5, v5]) and (assuming your counter doesn't reset within the interval) will return (v5 - v1) / (t5 - t1). I.e. it actually computes the rate of increase over ~4s rather than 5s.

increase(counter[5s]) will return (v5 - v1) / (t5 - t1) * 5, so the rate of increase over ~4 seconds, extrapolated to 5 seconds.

Due to the samples not being exactly spaced, both rate and increase will often return floating point values for integer counters (which makes obvious sense for rate, but not so much for increase).

Answer from Alin Sînpălean on Stack Overflow
Top answer
1 of 3
273

In an ideal world (where your samples' timestamps are exactly on the second and your rule evaluation happens exactly on the second) rate(counter[1s]) would return exactly your ICH value and rate(counter[5s]) would return the average of that ICH and the previous 4. Except the ICH at second 1 is 0, not 1, because no one knows when your counter was zero: maybe it incremented right there, maybe it got incremented yesterday, and stayed at 1 since then. (This is the reason why you won't see an increase the first time a counter appears with a value of 1 -- because your code just created and incremented it.)

increase(counter[5s]) is exactly rate(counter[5s]) * 5 (and increase(counter[2s]) is exactly rate(counter[2s]) * 2).

Now what happens in the real world is that your samples are not collected exactly every second on the second and rule evaluation doesn't happen exactly on the second either. So if you have a bunch of samples that are (more or less) 1 second apart and you use Prometheus' rate(counter[1s]), you'll get no output. That's because what Prometheus does is it takes all the samples in the 1 second range [now() - 1s, now()] (which would be a single sample in the vast majority of cases), tries to compute a rate and fails.

If you query rate(counter[5s]) OTOH, Prometheus will pick all the samples in the range [now() - 5s, now] (5 samples, covering approximately 4 seconds on average, say [t1, v1], [t2, v2], [t3, v3], [t4, v4], [t5, v5]) and (assuming your counter doesn't reset within the interval) will return (v5 - v1) / (t5 - t1). I.e. it actually computes the rate of increase over ~4s rather than 5s.

increase(counter[5s]) will return (v5 - v1) / (t5 - t1) * 5, so the rate of increase over ~4 seconds, extrapolated to 5 seconds.

Due to the samples not being exactly spaced, both rate and increase will often return floating point values for integer counters (which makes obvious sense for rate, but not so much for increase).

2 of 3
50

Prometheus calculates rate(counter[d]) at timestamp t in the following way:

  1. It selects raw samples for the counter time series on the time range (t-d ... t]. Note that the t-d timestamp isn't included in the time range, while t timestamp is included in the time range. If the selected time range contains less than two raw samples, then Prometheus returns an empty value (a gap) at the timestamp t.
  2. Then it calculates the increase of the selected raw samples. Usually it is calculated as the difference between the last selected sample and the first selected sample. Calculations become slightly complicated if the counter was reset to zero during the selected time range. Let's skip this for the sake of clarity.
  3. Then the resulting increase can be extrapolated if timestamps for the first and/or the last raw samples are located too far from the bounds of the selected time range.
  4. Then the rate is calculated by dividing the extrapolated increase by d.

Prometheus calculates increase(counter[d]) in the same way except the last step.

Let's look at a few examples applied to the original data:

second   counter_value    increase calculated by hand(call it ICH from now)
1             1                    1
2             3                    2
3             6                    3
4             7                    1
5            10                    3
6            14                    4
7            17                    3
8            21                    4
9            25                    4
10           30                    5
  • The rate(counter[1s]) will return nothing at any timestamp t, since any time range (t-1s ... t] contains only a single raw sample, while Prometheus requires at least two samples for calculating both rate() and increase().

  • The rate(counter[2s]) and increase(counter[2]) would return the following values per each timestamp t when extrapolation isn't applied:

t       counter_value    rate(counter[2s])        increase(counter[2s])
1             1                    -                       -
2             3               (3-1)/2=1.0                3-1=2
3             6               (6-3)/2=1.5                6-3=3
4             7               (7-6)/2=0.5                7-6=1
5            10              (10-7)/2=1.5               10-7=3
6            14             (14-10)/2=2                14-10=4
7            17             (17-14)/2=1.5              17-14=3
8            21             (21-17)/2=2                21-17=4
9            25             (25-21)/2=2                25-21=4
10           30             (30-25)/2=2.5              30-25=5

In reality Prometheus results for rate(counter[2s]) and increase(counter[2s]) may be slightly bigger because of extrapolation, since the first sample on the selected time range is located comparatively far from the start of the time range.

Such calculations have the following issues:

  • Prometheus can return fractional results from increase() over time series, which contains only integer values. This is because of extrapolation. For example, Prometheus may return fractional results from increase(http_requests_total[5m]).

  • Prometheus returns empty results (aka gaps) from increase(counter[d]) and rate(counter[d]) when the lookbehind window d doesn't cover at least two samples - see rate(counter[1s]) and increase(counter[1s]) example above.

  • Prometheus completely misses the increase between the raw sample just before the (t-d ... t] interval and the first raw sample on this interval. This may result in inaccurate calculations. For example, increase(counter[1h]) doesn't equal to sum_over_time(increase(counter[1m])[1h:1m]).

Prometheus developers are aware of these issues - see this link. These issues are addressed in the system I work on - VictoriaMetrics - more specifically, in MetricsQL query language - see this comment and this article for technical details.

🌐
Last9
last9.io › blog › grafana-rate-function
Why Grafana's Rate Function Is Your Dashboard's Best Kept Secret | Last9
April 25, 2025 - ... If you’d like to continue ... connect with other DevOps engineers and SREs. The rate() function in Grafana calculates how fast a counter metric is increasing per second....
Discussions

Difficulties to display the right information with rate/increase PromQL function
Hi, I’m having some difficulties to display some values and to interprete them. My setup is : sFlow RT and Prometheus Exporter (to export network metrics in bits/sec) => Prometheus (where metrics are created/filtered) => Grafana (to display metrics, in Gbits/sec) Prometheus sFlow metrics ... More on community.grafana.com
🌐 community.grafana.com
4
0
April 23, 2025
rate()/increase() extrapolation considered harmful
I've been trying to deal with the errors introduced by the rate() and increase() functions for so long that I keep going back every few months and spend a couple of hours tweaking Grafana dashboards before I remember that there is literally no way of getting an accurate result out of them short ... More on github.com
🌐 github.com
56
January 26, 2018
How does prometheus rate works with grafana? - Stack Overflow
15 Understanding increase() and rate() used on http_server_requests_seconds_count with prometheus and Grafana More on stackoverflow.com
🌐 stackoverflow.com
Calculate increase of a maximum over last 24h
Hi all, it´s probably (well most probably) a noob question, but that´s because I really AM a grafana noob 😃 I´ve got a max value (at the moment 48543 kg) that increases every day (a few times over the day) by a few kg since > 13 years. Now I want to show a graph with the daily (last 24h ... More on community.grafana.com
🌐 community.grafana.com
4
0
November 19, 2023
🌐
SigNoz
signoz.io › guides › what is the difference between prometheus rate vs increase functions
Prometheus rate vs increase Functions Explained | SigNoz
June 23, 2026 - Choose between rate() and increase() based on your specific monitoring needs. Proper use of these functions is crucial for accurate data interpretation and alerting. For more on Prometheus, the Prometheus alternatives roundup goes broader, and the Prometheus vs Grafana, OpenTelemetry vs Prometheus, ...
🌐
Grafana
community.grafana.com › prometheus
Difficulties to display the right information with rate/increase PromQL function - Prometheus - Grafana Labs Community Forums
April 23, 2025 - Hi, I’m having some difficulties to display some values and to interprete them. My setup is : sFlow RT and Prometheus Exporter (to export network metrics in bits/sec) => Prometheus (where metrics are created/filtered) => Grafana (to display metrics, in Gbits/sec) Prometheus sFlow metrics ...
🌐
Hoelz
hoelz.ro › blog › use-caution-when-using-rate_interval-along-with-increase
Use caution when using $rate_interval along with increase()
We were looking at increase(detected_changes_count[$__interval]), which is Grafana-speak for "how much did detected_changes_count increase between points on this graph?". One thing we changed pretty quickly was to replace $__interval with $__rate_interval, which I had recently read about.
🌐
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 - Now, using either the Prometheus UI or Grafana Explore, we can inspect each metric and its corresponding values in real time. In the visual diagram below, you’ll see that we’re querying the same metric we discussed earlier — http_requests_total — and filtering for data within the last 1 hour. ... Since http_requests_total is a counter metric, its value increases ...
Find elsewhere
🌐
Timesofcloud
timesofcloud.com › home › prometheus grafana
Prometheus & Grafana — Rate & Increase -
March 30, 2026 - Rate & IncreaseCounters only go up. By themselves, they’re not very useful — knowing the total number of requests since the server started doesn’t tell you if the server is busy right now. That’s where rate() and increase() come in.Why You Need rate()Counter value over time:Value │1500│ ● │ ●1200│ ● │ ● 900│ ● │ ● 600│ ● │● 300│ └──────────────────────────────────── Time 8am 9am 10am 11am 12pm 1pm"We've had 1500 requests" — not actionable"We're getting 5 requests/second" —
🌐
DoiT
doit.com › home › blog › making peace with prometheus rate()
Making peace with Prometheus rate() | DoiT
February 17, 2023 - You see, depending on how stars align if our 1-minute range buckets land just on metric change boundaries, there is no change in the metric within that bucket at all and this is exactly why rate(), together with its sister increase(), returns zeroes. Why does it reproduce so often and so consistently? Two factors: If you have a thing in your code that reports change around a whole minute(s) (think cronjobs), then it’s likely that the change will be attributed to the whole-minute boundary when scraping. As of two years ago, Grafana makes sure (and rightfully so) to align the start of the chart range to be a multiple of step, hence if your step in Grafana is one minute, the bucket boundaries will always fall on a whole-minute boundary, e.g.
🌐
GitHub
github.com › prometheus › prometheus › issues › 3746
rate()/increase() extrapolation considered harmful · Issue #3746 · prometheus/prometheus
January 26, 2018 - To me it makes a lot of sense to use actual data instead of fabricated (extrapolated) data when computing rates/increases (which, I don't have to point out but I will, is the whole reason for the existence of counters). But it's possible it's only me. ... If you're not tired by now, there are a couple more things I should add. For one, I am aware that one could hardcode the increase range and adjust the result accordingly into the Grafana dashboard, but over a high enough range this will result in even worse data sampling, as you'd now be seeing increase(foo[15s]) with a 30 minute resolution.
Author: prometheus
🌐
MetricFire
metricfire.com › blog › understanding-the-prometheus-rate-function
How the Prometheus rate() function works | MetricFire
March 12, 2026 - Increasing the time range would achieve the opposite - the resulting line (if you plotted the results) would become “smoother”, and it would be harder to spot the spikes. Thus, the recommendation is to put the time range into a different ...
🌐
Google Groups
groups.google.com › g › prometheus-users › c › jqEt-FkJo0o
overhead of rate vs increase
On the other hand, the increase() function would fetch the first and last data point + penultimate data points for interpolation/extrapolation. Is it correct to state that increase() has lower overhead than rate() in terms of samples fetched with the overhead scaling up with time range interval?
🌐
GitConnected
levelup.gitconnected.com › conquer-promql-how-rate-and-increase-work-38d0acf91a0d
Conquer PromQL — How Rate and Increase Work | by Guy Erez | Level Up Coding
April 16, 2023 - Prometheus visualization — https://prometheus.io/docs/visualization/grafana/ Let’s start with increase() as it makes it much easier to understand rate(). When I read the documentation I felt like I needed a degree in statistics to make sense of it. So let’s break it down in simple terms: Let’s say you’re measuring the number of failed requests to your server.
🌐
Last9
last9.io › blog › prometheus-rate-function
Prometheus Rate Function: A Practical Guide to Using It | Last9
June 15, 2026 - The rate() function is a key component of PromQL (Prometheus Query Language) used for analyzing the rate of change in counter metrics over time. At its core, rate() calculates the per-second average rate of increase of time series in a range vector.
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › functions
Query functions | Prometheus
increase should only be used with counters (for both floats and histograms). It is syntactic sugar for rate(v) multiplied by the number of seconds under the specified time range window, and should be used primarily for human readability.
🌐
Medium
medium.com › @pradeepsunku › mastering-prometheus-queries-in-grafana-99b3849b1e03
Mastering Prometheus Queries in Grafana | by PradeepSunku | Medium
August 10, 2024 - For instance, if you're calculating the total number of requests in the selected range, you might use increase(http_requests_total[$__range]) to get the cumulative increase over the displayed period.
🌐
OneUptime
oneuptime.com › home › blog › how to use selected time period in grafana queries
How to Use Selected Time Period in Grafana Queries
December 17, 2025 - # Problem: First data point shows spike rate(metric[5m]) # Solution: Use $__rate_interval or a longer range vector rate(metric[$__rate_interval]) # or, for totals increase(metric[$__range]) Use $__rate_interval for rates: Prevents inaccurate calculations · Use $__range for totals: Shows cumulative values over selection · Set appropriate min intervals: Prevents too many data points · Test with different ranges: Verify queries work at 5m, 1h, 24h, 7d · Document variable usage: Help team members understand queries · Grafana's time variables make dashboards dynamic and responsive to user selections:
🌐
Grafana
community.grafana.com › prometheus
Calculate increase of a maximum over last 24h - Prometheus - Grafana Labs Community Forums
November 19, 2023 - Hi all, it´s probably (well most probably) a noob question, but that´s because I really AM a grafana noob 😃 I´ve got a max value (at the moment 48543 kg) that increases every day (a few times over the day) by a few kg since > 13 years. Now I want to show a graph with the daily (last 24h ...
🌐
Chris's Wiki
utcc.utoronto.ca › ~cks › space › blog › sysadmin › GrafanaOurIntervalSettings
How we choose our time intervals in our Grafana dashboards
August 7, 2020 - The more complete answer is that we use $__interval but often tell Grafana that there is a minimum interval for the query that is usually slightly larger than how often we generate the metric. When you use rate(), increase(), and their kin, you need to make sure that your interval always has at least two metric points, otherwise they give you no value and your graphs look funny.