Prometheus calculates increase(m[d]) at timestamp t in the following way:

  1. It fetches raw samples stored in the database for time series matching m on a time range (t-d .. t]. Note that samples at timestamp t-d aren't included in the time range, while samples at t are included. It is expected that every selected time series is a counter, since increase() works only with counters.
  2. It calculates the difference between the last and the first raw sample value on the selected time range individually per each time series matching m. Note that Prometheus doesn't take into account the difference between the last raw sample just before the (t-d ... t] time range and the first raw samples at this time range. This may lead to lower than expected results in some cases.
  3. It extrapolates results obtained at step 2 if the first and/or the last raw samples are located too far from time range boundaries (t-d .. t]. This may lead to unexpected results. For example, fractional results for integer counters. See this issue for details.

Prometheus calculates rate(m[d]) as increase(m[d]) / d, so rate() results may be also unexpected sometimes. Prometheus developers are aware of these issues and are going to fix them eventually - see these design docs.

In the meantime you can use VictoriaMetrics - this is Prometheus-like monitoring solution I work on. It provides increase() and rate() functions, which are free from issues mentioned above.

Answer from valyala on Stack Overflow
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › functions
Query functions | Prometheus
The counts in the buckets are monotonically increasing (strictly non-decreasing).
🌐
SigNoz
signoz.io › guides › what is the difference between prometheus rate vs increase functions
Prometheus rate vs increase Functions Explained | SigNoz
June 23, 2026 - Rate() calculates per-second average change; increase() shows total change over time. Both functions are essential for analyzing counter metrics in Prometheus.
Discussions

spring - Understanding increase() and rate() used on http_server_requests_seconds_count with prometheus and Grafana - Stack Overflow
It is expected that every selected time series is a counter, since increase() works only with counters. It calculates the difference between the last and the first raw sample value on the selected time range individually per each time series matching m. Note that Prometheus doesn't take into ... More on stackoverflow.com
🌐 stackoverflow.com
Prometheus increase result problem - General Help/Support - Prometheus Monitoring System
hi everyone, When I use increase function to calculate the increment, I expected an integer, but a value with a decimal appeared instead. First, I check the value was 913028805. Then I made the value up to 913029005, … More on discuss.prometheus.io
🌐 discuss.prometheus.io
0
April 19, 2024
increase() in Prometheus sometimes doubles values: how to avoid? - Stack Overflow
I've found that for some graphs I get doubles values from Prometheus where should be just ones: Query I use: increase(signups_count[4m]) Scrape interval is set to the recommended maximum of 2 min... 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
🌐
OneUptime
oneuptime.com › home › blog › how to understand rate() vs increase() in prometheus
How to Understand rate() vs increase() in Prometheus
December 17, 2025 - # Show total count in dashboard increase(http_requests_total[1h]) Both functions handle counter resets (when the counter goes back to zero after a restart): sequenceDiagram participant C as Counter participant P as Prometheus C->>P: Value: 100 C->>P: Value: 150 Note right of P: Normal increase: 50 C->>P: Value: 200 Note right of P: Normal increase: 50 C->>P: Value: 0 (restart) C->>P: Value: 30 Note right of P: Detects reset, adds<br/>post-reset increase
Top answer
1 of 2
18

Prometheus calculates increase(m[d]) at timestamp t in the following way:

  1. It fetches raw samples stored in the database for time series matching m on a time range (t-d .. t]. Note that samples at timestamp t-d aren't included in the time range, while samples at t are included. It is expected that every selected time series is a counter, since increase() works only with counters.
  2. It calculates the difference between the last and the first raw sample value on the selected time range individually per each time series matching m. Note that Prometheus doesn't take into account the difference between the last raw sample just before the (t-d ... t] time range and the first raw samples at this time range. This may lead to lower than expected results in some cases.
  3. It extrapolates results obtained at step 2 if the first and/or the last raw samples are located too far from time range boundaries (t-d .. t]. This may lead to unexpected results. For example, fractional results for integer counters. See this issue for details.

Prometheus calculates rate(m[d]) as increase(m[d]) / d, so rate() results may be also unexpected sometimes. Prometheus developers are aware of these issues and are going to fix them eventually - see these design docs.

In the meantime you can use VictoriaMetrics - this is Prometheus-like monitoring solution I work on. It provides increase() and rate() functions, which are free from issues mentioned above.

2 of 2
-1

Increase measure the increase in your window, and rate is the 'per second' rate.

So if you were to imagine that Prometheus write a database row each second of what the current value is. That helps reason through the metrics calculations.

  1. If the total so far was 0 then the metric increased by 5 in the last 10 seconds, the increase is looking back 10 seconds and finding the value and reporting the increase.

  2. The same as 1. but it is looking back 30 seconds.

  3. The 0.5 comes from looking at the window size (10s), measuring the increase them normalizing it to a 'per second' rate. So the increase of 5/10 seconds: .5 calls per second

  4. With the larger window, the 'per second' is spread over the larger window.

increase is easier to reason about, but rate standardizes on the 'per second' unit.

One problem with the 'per second' unit though is that it can be too small to talk through, but it makes it easy to multiple by 60 (to show a per minute) or 3600 (to show a per hour). The window is only used to calculate the window for how far to gather data for the calculation.

🌐
MetricFire
metricfire.com › blog › understanding-the-prometheus-rate-function
How the Prometheus rate() function works | MetricFire
March 12, 2026 - The rate() function in Prometheus is a fundamental tool for monitoring systems, enabling users to calculate the per-second average rate of increase of counter metrics over a specified time range.
🌐
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.
🌐
Better Stack
betterstack.com › community › questions › do-i-understand-prometheus-rate-vs-increase-correctly
Do I Understand Prometheus's Rate Vs Increase Functions Correctly? | Better Stack Community
December 2, 2024 - Use increase when you need to know the total amount of something that occurred (e.g., total requests over a time period). ... Get notified with a radically better infrastructure monitoring platform.
Find elsewhere
🌐
OneUptime
oneuptime.com › home › blog › how to calculate cumulative increase in prometheus
How to Calculate Cumulative Increase in Prometheus
December 17, 2025 - increase() automatically handles counter resets by detecting when a value drops and assuming it reset from zero. sequenceDiagram participant P as Prometheus participant M as Metric M->>P: Sample: 100 M->>P: Sample: 150 Note right of P: increase ...
🌐
Promlabs
promlabs.com › blog › 2021 › 01 › 29 › how-exactly-does-promql-calculate-rates
PromLabs | Blog - How Exactly Does PromQL Calculate Rates?
January 29, 2021 - Counters are a Prometheus metric type whose value only goes up, and which represent cumulative total counts like "How many requests have we handled in total?" or "How many seconds have we spent handling requests?". Since the value of a counter ...
🌐
Google Groups
groups.google.com › g › prometheus-users › c › V7IbFb-w4ag
Simple increase - sum of the metrics in time range with dynamic metric count
September 22, 2023 - Note that you don't need specifying lookbehind window in square brackets at increase(...), since VictoriaMetrics automatically sets it to the interval between points shown on the graph (aka step query arg automatically passed by Grafana to /api/v1/query_range - see https://prometheus.io/docs...
🌐
DoiT
doit.com › home › blog › making peace with prometheus rate()
Making peace with Prometheus rate() | DoiT
February 17, 2023 - So basically Prometheus understands that the actual range in each bucket is one scrape less, i.e. 45 seconds instead of 60 in our case, so when it sees metric changed by 1 in a bucket, it’s actually “by 1 in 45 seconds”, not “by 1 in 60 seconds”, so it extrapolates the result as 1 / 45 * 60 = 1.33 and this is how we end up with increase() values being larger than the actual change.
🌐
Prometheus
discuss.prometheus.io › general help/support
Prometheus increase result problem - General Help/Support - Prometheus Monitoring System
April 19, 2024 - Then I made the value up to 913029005, it should be 200 when I use increase{…[1m]} to calculate the value but it appeared to be 266.666. when I use increase{…[5m]}, it become close to 200.
Top answer
1 of 3
44

This is known as aliasing and is a fundamental problem in signal processing. You can improve this a bit by increasing your sample rate, a 4m range is a bit short with a 2m range. Try a 10m range.

Here for example the query executed at 1515722220 only sees the [email protected] and [email protected] samples. That's an increase of 1 over 2 minutes, which extrapolated over 4 minutes is an increase of 2 - which is as expected.

Any metrics-based monitoring system will have similar artifacts, if you want 100% accuracy you need logs.

2 of 3
21

increase() will always (approximately) double the actual increase with your setup.

The reason is that (as currently implemented):

  1. increase() is (as you observed) syntactic sugar for rate() i.e. it is the value that would be returned by rate() multiplied by the number of seconds in the range you specified. In your case, it is rate() * 240.
  2. rate() uses extrapolation in its computation. In the vast majority of cases a 4 minute range will return exactly 2 data points, almost exactly 2 minutes apart. The rate is then computed as the difference between last and first (i.e. the 2 points in your case) divided by the time difference of the 2 points (around 120 seconds in 99.99% of cases) multiplied by the range you requested (exactly 240 seconds). So if the increase between the 2 points is zero, the rate is zero. If the increase between the 2 points is 1.0, the computed rate() will be close to 2.0 / 240 and, as a result, the increase() will be 2.0.

This approach works mostly fine with counters that increase smoothly (e.g. if you have a more or less fixed number of signups every 2 minutes). But with a counter that rarely increases (as does your signups counter) or a spiky counter (like CPU usage) you get weird overestimates (like the increase of 2 you are seeing).

You can essentially reverse engineer Prometheus' implementation and get (something very close to) the actual increase by multiplying with (requested_range - scrape interval) and dividing by requested_range, essentially walking back the extrapolation that Prometheus does.

In your case, this would mean

increase(signups_count[4m]) * (240 - 120) / 240

or, more succinctly,

increase(signups_count[4m]) / 2

It requires you to be aware both of the length of the range and the scrape interval, but it will give you what you want: "ones for ones, and twos for twos, most of the time". Sometimes you'll get 1.01 instead of 1.0 because the scrapes were 119 seconds, not 120 seconds apart and sometimes, if your evaluation is closely aligned with the scrape some points right on the boundary might be included or not in a data point calculation, but it's still a better answer than 2.0.

🌐
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.
🌐
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 - You can see the irate function doesn’t consider all the values in a time range and that is how it is designed and that is the reason why the prometheus document recommends the irate function for the fast-moving counter rather than the slow-moving counter. There is a problem with the irate function since it doesn’t consider all the values in the time range. There is a high chance of missing a spike if the spike falls under un-considered values in a given time range. This is clearly explained in this blog. Now let’s jump into the last function which is the increase function
🌐
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 :smiley: I´ve got a max value (at the moment 48543 kg) that increases every day (a few times over the day) by a …
🌐
DoHost
dohost.us › home › 2025 › september › 28 › understanding rate vs. increase in promql
Understanding Rate vs. Increase in PromQL - DoHost
September 28, 2025 - You’ll learn when to use `rate()` to smooth out counter resets and when `increase()` provides a more accurate total change over a specific time window. We’ll also discuss potential pitfalls and best practices for leveraging these functions in your Prometheus monitoring setup.
🌐
GitConnected
levelup.gitconnected.com › prometheus-counter-metrics-d6c393d86076
Working With Prometheus Counter Metrics | Level Up Coding
February 28, 2022 - Prometheus’ increase function calculates the counter increase over a specified time frame². The following PromQL expression calculates the number of job executions over the past 5 minutes.
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.

🌐
Reddit
reddit.com › r/prometheusmonitoring › how to deal with increase function and no data points
r/PrometheusMonitoring on Reddit: How to deal with Increase function and no data points
September 3, 2021 -

I need to use the increase function, but the metric is very rare and when service restarts the counter is null for long time. The increase metric doesn’t play nicely with the null value and I can find a solution to consider null as zero.

Increase(my_counter[1h])

Works only if there are no null data points. Any other query I tried do not work like

Increase(my_metrics[1h] or vector(0))