http_requests_total could be several timeseries each with their own labels. Think of it in two dimensions:
max_over_time(http_requests_total[5m])
This will return the same set of timeseries as you had before, but for each one giving the maximum over the 5 minute window.
http_requests_total{instance="A"} max(a1,a2,a3,a4,a5)
http_requests_total{instance="B"} max(b1,b2,b3,b4,b5)
http_requests_total{instance="C"} max(c1,c2,c3,c4,c5)
Aside: this is probably *not* what you want to do with a counter - you might want to use rate() on it first. But it makes sense with a gauge.
In the other dimension:
max(http_requests_total)
As an instant query, you'll get just the most recent time:
http_requests_total max(a5,b5,c5)
but if you graph this, the instant time will be swept over the graph window, so you'll see the max across timeseries at each point in time. Again, this probably doesn't make sense with counters as they have arbitrary offsets, but maximum across gauges makes sense (e.g. show me the maximum temperature).
If you want to do aggregation over time on this expression, you can turn it back into a range vector using a
subquery: e.g.
(max(http_requests_total))[5m:1m]
That calculates the max(http_requests_total) at the current time and at 1 minute intervals over the previous 5 minutes. You then have a range vector that you can aggregate over time.
max_over_time (rate(http_requests_total[5m])[60m:1m])
i.e. calculate the 5-minute average rate at 1 minute intervals, and give me the maximum rate seen over the last 60 minutes.