Glossary · History

Bounding value

A bounding value is the raw stored value immediately outside a requested history interval, which the server uses to establish or interpolate the value at the interval edge. Aggregates and interpolative reads need it, and when no bound exists within the server's search limits you get BadBoundNotFound instead of a silently wrong first point.

Why an edge needs a value from outside

History is stored on change, so there is usually no stored point exactly at your start time. To know what the variable was at 06:00:00 the server must look back to the last point before it, which is the bounding value. Without it there is no defensible value at the interval start, and every time-weighted aggregate over that interval would be missing its first weight.

Where you meet it explicitly

ReadRawModifiedDetails has a ReturnBounds flag. With it set, a raw read returns the bounding values on both sides of your window in addition to the values inside it, so a client can render a correct trend line that starts at the left edge of the chart rather than at the first stored point. Aggregates and the Interpolative aggregate use bounds internally whether or not you asked for them.

Stepped or interpolated changes the answer

How the bound is used depends on the variable's interpolation behaviour. A stepped variable takes the bounding value as-is until the next stored point; a non-stepped variable is linearly interpolated between the bounding value and the first value inside the window. The same request against the same raw data therefore yields different edge values on servers configured differently, which is a common cause of two systems disagreeing by a few percent on the same shift.

When there is no bound

Servers limit how far back they will search for a bound, and there may genuinely be nothing: history starts after your start time, or the archive was purged. The response then carries BadBoundNotFound for that point rather than fabricating a value, and Uncertain status can be returned where a bound was found but is too old to be trustworthy. Handle it by shortening the window or by accepting the first stored value as the start, and record which you did.

Example

A raw read with ReturnBounds - note the two values outside the window

Request window: 06:00:00Z - 07:00:00Z, ReturnBounds = true

Stored history:
  05:41:12   72.4    <- bounding value before the window
  06:18:03   73.1
  06:47:55   71.8
  07:12:40   70.9    <- bounding value after the window

Returned with ReturnBounds = true:
  06:00:00   72.4  (stepped: value at the edge, from the 05:41 bound)
  06:18:03   73.1
  06:47:55   71.8
  07:00:00   71.8  (stepped: still holding at the closing edge)

Without the bound the interval would start at 06:18 and any TimeAverage
would silently omit the first 18 minutes.

No point before 06:00 within the server's search limit -> BadBoundNotFound
The mistake people make: Reading raw history without ReturnBounds and then computing an average client-side. The first stored point inside the window becomes the de facto start, so the leading gap is dropped and the result is biased with no error raised. Ask for bounds, or let the server compute the aggregate.

Defined in: Part 11 - Historical Access, with the edge rules in Part 13 - Aggregate Functions.

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Server Acceptance Test Pack
A 40-check acceptance test you run against a vendor's server before commissioning sign-off. Weighted scoring, three hard gates, and a one-page verdict for the supplier meeting.
Get the free test pack →
Free, no course, no login