Concluded·24 Aug 2026 · 4 min read

What a deadband actually costs

TimescaleDB on PostgreSQL 16 · estate_tag_history, 334,808 rows across 3 sites × 6 tags · deadband simulated in Python against stored values

The question: what does a historian deadband actually buy, and what does it cost?

Both halves are measurable against stored data, so I measured them rather than reasoning about them.

The rig

Sourceestate_tag_history in TimescaleDB, 334,808 rows
Series3 sites (Rotterdam, Houston, Leipzig) × 6 tags = 18 distinct series
Window2026-08-07 to 2026-08-19
Methodreplay stored values in timestamp order per series, simulating a deadband against the last retained value
Thresholds0.1%, 0.5%, 1%, 2%, 5% of each series' own observed span

What this data is, honestly. These are continuously-moving generated signals — ramps and sine waves — not process measurements from a real plant. That limits one claim and strengthens another. It means I cannot tell you what fraction of a real historian is redundant, because real tags sit still for long periods and these never do — the trap in testing a historian with fake data, and the reason this piece makes no claim about redundancy. It does mean the compression figures here are a floor: a real plant will do better. And because the underlying shape is exactly known, the reconstruction error is measured against ground truth rather than estimated.

The bug that came first

The first run produced a clean-looking table that was entirely meaningless, and it is worth recording because the output looked fine.

estate_tag_history is keyed on (site, tag_path, ts). I grouped by tag_path alone. Three sites publishing the same tag name therefore interleaved into one series, so the simulation compared each reading against a reading from a different site.

grouped by tag_path
three sites interleaved · reported 22.1% mean saving
grouped by site + tag_path
one real series · correct figure 41.1%
The same query, grouped two ways. Grouping by tag_path alone interleaves three sites into one series; adding site to the grouping recovers the signal. Only the picture made this obvious.

Every consecutive delta was inflated, so retention looked far higher and savings far lower than the truth. At 1% the broken run reported a 22.1% mean saving; the correct figure is 41.1%. It did not error, and nothing in the numbers looked impossible.

What caught it was drawing the waveform. A sine plotted from the query zigzagged between 31 and 305 — which no sine does. The table was plausible and the picture was not, which is a good argument for always drawing the thing.

Retention against error

0.1% thresholdmean 3% saved · range 07% · worst error 0.05%
0.5% thresholdmean 23.1% saved · range 049.9% · worst error 0.35%
1.0% thresholdmean 41.1% saved · range 066.6% · worst error 0.672%
2.0% thresholdmean 60.6% saved · range 082.9% · worst error 1.836%
5.0% thresholdmean 84.9% saved · range 65.992.8% · worst error 4.786%
pale band = spread across the 18 series · line = mean · at every threshold below 5%, some series saves nothing
Mean saving with the full per-series range behind it, and the worst-case error each threshold guarantees. The error column behaves; the saving column does not.
thresholdmean savedmin savedmax savedmean worst-case errormean error
0.1%3.0%0.0%7.0%0.050%0.002%
0.5%23.1%0.0%49.9%0.350%0.081%
1.0%41.1%0.0%66.6%0.672%0.251%
2.0%60.6%0.0%82.9%1.836%0.651%
5.0%84.9%65.9%92.8%4.786%2.181%

Errors are expressed as a percentage of each series' span.

Two things stand out. Error tracks the threshold almost exactly — a 1% deadband produces a worst-case error a shade under 1%, which is the guarantee the mechanism is supposed to give, and it holds. Saving does not track the threshold at all. At every setting below 5%, at least one series saves nothing.

The spread is the finding

Sine2 ×3, Ramp1 ×3
66.4 – 66.6%
Sine1 ×3
63.6 – 63.8%
Sine0 ×3
50.1%
Ramp0 ×3, Ramp2 ×3
0.0%
At a 1% threshold the eighteen series land in four tight clusters with nothing between them. Shape decides the outcome, and the same six signals get no benefit at all.

At a 1% threshold, the eighteen series fall into three groups with nothing in between:

seriessaved at 1%
Sine/Sine2 (×3 sites), Ramp/Ramp1 (×3)66.4% – 66.6%
Sine/Sine1 (×3)63.6% – 63.8%
Sine/Sine0 (×3)50.1%
Ramp/Ramp0 (×3), Ramp/Ramp2 (×3)0.0%

Ramp/Ramp2 has a span of 1.0 and Ramp/Ramp0 a span of 10.0; both traverse their range fast enough that every consecutive sample already exceeds 1% of it. The deadband is not compressing them slightly — it is doing nothing at all, while consuming a config field that suggests otherwise.

Raise those two to 5% and they drop 65.9% and 79.9% respectively. The threshold that is correct for them is nowhere near the one that is correct for Sine/Sine2.

What the reconstruction looks like

40 readingsamber = the error you will never see
Zoomed to forty readings. The vertical gaps are the error: exact at every stored point, entirely invented in between, and indistinguishable afterwards from a signal that genuinely sat still.

140 consecutive readings from Rotterdam / Sine/Sine0, span 98.99, at a 5% threshold: 19 readings retained. The stored series is a staircase whose corners are correct and whose middles are invented by whatever draws the chart later.

Worth being precise about what is lost: not accuracy at the stored points, which is exact, but everything between them. A four-second excursion occurring between two retained samples leaves no trace whatsoever, and nothing downstream can distinguish "flat" from "not recorded".

Verdict

The error guarantee holds and is predictable. The saving does not, and is not.

That asymmetry is the practical result: a deadband is safe to set and impossible to justify globally. You can promise a bound on error from the threshold alone, but you cannot promise a byte of saving without measuring the signal — and a third of the signals here return exactly nothing for it.

Set it per tag, against the smallest movement anybody will ever need to see. It is the one setting whose mistakes cannot be corrected afterwards.

The argument for a general audience is in your historian is throwing readings away on purpose.

Newsletter

New essays, by email.

SCADA, cloud, AI, and the plant floor — a short email when something new is published. No noise, unsubscribe anytime.