The challenge with calculating this number is that we only have a few data points inside a time range, and they tend not to be at the exact start and end of that time range (1 minute here). What do we do about the time between the start of the time range and the first data point, similarly the last data point and the end of the range?

We do a small bit of extrapolation to smooth this out and produce the correct result in aggregate. For very slow moving counters like this it can cause artifacts.

Answer from brian-brazil on Stack Overflow
Top answer
1 of 2
22

The challenge with calculating this number is that we only have a few data points inside a time range, and they tend not to be at the exact start and end of that time range (1 minute here). What do we do about the time between the start of the time range and the first data point, similarly the last data point and the end of the range?

We do a small bit of extrapolation to smooth this out and produce the correct result in aggregate. For very slow moving counters like this it can cause artifacts.

2 of 2
8

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

  1. It selects all the raw samples per each time series with foo_requests_total name on the time range (t-1m ... t]. Note that samples at the timestamp t-1m aren't included in the selection, while samples at the timestamp t are included in the selection.
  2. It calculates the difference d between the last and the first raw sample on the selected time range (Prometheus may also remove possible counter resets, but let's skip this step for the sake of clarity).
  3. It extrapolates the calculated difference d if the first and/or the last raw sample are located too far from the bounds of the selected time range.

The last step may result in fractional increase() values over integer counters as seen in the original question. See this issue for more details. Note also that increase() in Prometheus misses the difference between the first raw sample on the selected time range and the previous sample before the selected time range. This may result in smaller than expected increase() results.

Prometheus developers are going to fix these issues - see this design doc. In the mean time try VictoriaMetrics - its increase() function properly returns the expected integer result without any extrapolation over integer counters.

🌐
Google Groups
groups.google.com › g › prometheus-users › c › _aK7im7elUs
Why does increase() return fractional results for integer-valued metrics?
For the majority of cases looking ... values are actually floats, so could have fractional parts. If wanted you could use one of the rounding functions to force the returned value to be an integer....
Discussions

Surprising (incorrect?) behaviour of "increase" function
The description for the increase function says that it "calculates the increase in the time series in the range vector." So if I have a counter that's only changed in integer incremen... More on github.com
🌐 github.com
4
May 5, 2017
prometheus - Increase() vs changes() function for counters - Stack Overflow
I have a gift-certificates application that increases Prometheus counter whenever someone activates a certificate. Now I want to put simple number in Grafana board that shows me how many certificates were activated last 24h. I can do that by increase(gift_certificates_activated_total[24h]) query, but it gives float results, something like 105.01287565915334. But what I found is if I use changes function, it gives me the exact integer ... More on stackoverflow.com
🌐 stackoverflow.com
Python "prometheus_client", how to get an int value?
You're not doing anything wrong. There's no issue with it being a float. Prometheus will parse metric values as floats . More on reddit.com
🌐 r/PrometheusMonitoring
8
2
July 26, 2018
Proposal for improving rate, increase, delta (based on xrate, xincrease)
integer counters always return integer increases for all possible query intervals; the first counter increase from the origin is counted rather than ignored; missed or late scrapes never lead to missing results; ... Here is a Design Doc with a detailed explanation including examples: Prometheus ... More on github.com
🌐 github.com
13
October 11, 2023
🌐
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.
🌐
Prometheus
prometheus.io › docs › prometheus › latest › querying › functions
Query functions | Prometheus
Breaks in monotonicity (such as counter resets due to target restarts) are automatically adjusted for. The increase is extrapolated to cover the full time range as specified in the range vector selector, so that it is possible to get a non-integer result even if a counter increases only by integer increments.
🌐
GitHub
github.com › prometheus › prometheus › issues › 2683
Surprising (incorrect?) behaviour of "increase" function · Issue #2683 · prometheus/prometheus
May 5, 2017 - The description for the increase function says that it "calculates the increase in the time series in the range vector." So if I have a counter that's only changed in integer increments, I take it to mean that the result of increase should also ...
Author: prometheus
🌐
OneUptime
oneuptime.com › home › blog › how to calculate cumulative increase in prometheus
How to Calculate Cumulative Increase in Prometheus
December 17, 2025 - Solution: Use ceil() or floor() if you need integers: ceil(increase(http_requests_total[5m])) Calculating cumulative increase in Prometheus requires understanding how counters work and using increase() appropriately.
🌐
Promlabs
promlabs.com › blog › 2021 › 01 › 29 › how-exactly-does-promql-calculate-rates
PromLabs | Blog - How Exactly Does PromQL Calculate Rates?
January 29, 2021 - Let's look in more detail at how ... of the rate() and increase() functions. As an example, increase() can return non-integer results like 2.5883 even for counters that only have integer increments....
Find elsewhere
🌐
LinkedIn
linkedin.com › posts › julius-volz_understanding-counter-rates-and-increases-activity-7084180724525715456-gQ_P
Julius Volz on LinkedIn: Understanding Counter Rates and Increases in PromQL | Reset Handling…
July 10, 2023 - Why Prometheus interpolates increase() results and doesn't take into account the difference between the first raw samples on the lookbehind window and the previous raw sample. This is the main source of confusion for Prometheus users, who get unexpected results from increase() over slow-changing integer counter.
🌐
GitConnected
levelup.gitconnected.com › prometheus-counter-metrics-d6c393d86076
Working With Prometheus Counter Metrics | Level Up Coding
February 28, 2022 - Prometheus extrapolates increase to cover the full specified time window. Because of this, it is possible to get non-integer results despite the counter only being increased by integer increments¹.
🌐
Reddit
reddit.com › r/prometheusmonitoring › python "prometheus_client", how to get an int value?
r/PrometheusMonitoring on Reddit: Python "prometheus_client", how to get an int value?
July 26, 2018 -

Hello all,

I'm using Python prometheus_client and using Counter as my main way to print my results to http respond.

The only thing is.. the value is coming out as float, any way to make it int?

Here is an example of what I do:

value = 1
key = 'WooHoo_woo_hoo'
counter = Counter(key, '', ['name'])
counter.labels('MyName').inc(value)

The result is always... float:

WooHoo_woo_hoo{name="MyName"} 1.0

Any way to "fix" this? What am I doing wrong?

Thank you.

🌐
GitHub
github.com › prometheus › prometheus › issues › 12967
Proposal for improving rate, increase, delta (based on xrate, xincrease) · Issue #12967 · prometheus/prometheus
October 11, 2023 - integer counters always return integer increases for all possible query intervals; the first counter increase from the origin is counted rather than ignored; missed or late scrapes never lead to missing results; ... Here is a Design Doc with ...
Author: prometheus
🌐
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
🌐
Medium
pramodshehan.medium.com › prometheus-counter-metrics-1b0a4cbb79e1
Prometheus Counter metrics. There are three functions to calculate… | by Pramod Shehan | Medium
January 18, 2026 - increase()- Calculates the total absolute increase over the time window. Extrapolates the counter’s change to cover the full time range specified by the range vector selector. Because of this extrapolation, the result can be non-integer, even ...
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.

🌐
Stackprinter
stackprinter.com › export
Do I understand Prometheus's rate vs increase functions correctly?
Prometheus can return fractional results from increase() over time series, which contains only integer values. This is because of extrapolation.
Author: prometheus
🌐
GitHub
github.com › prometheus › prometheus › issues › 3806
Proposal for improving rate/increase · Issue #3806 · prometheus/prometheus
February 6, 2018 - The alternative is to do what the current implementation does, i.e. to compute the rate first (which would be ~constant for a smoothly increasing counter) and multiply it by the range. It would yield essentially the same result for the multiple of the scrape interval case (as the difference between the timestamps of the 2 ends would be ~= to the range) and smooth (but not integer) increases for the arbitrary range case.
Author: prometheus