The Rollup Nothing Ever Filled — A Correction
We published that this product stored no daily metrics and computed every dashboard figure from scratch. It was wrong, it was on this page, and the reason it was wrong is worth more than the original article: the check was run against the wrong thing entirely.
In August we audited our own product and published a finding: there was a table designed to hold a daily value for a named metric, and nothing had ever written to it. Every figure on every dashboard, we said, was therefore computed live at the moment you looked.
The second half of that sentence was false. Dashboard history is precomputed nightly, has been since the middle of that month, and is read from storage every time somebody opens the screen.
This page is the correction. It is also, now, a more useful article than the one it replaces — because the interesting question is no longer how our dashboards work. It is how a careful person checked a claim about software, got a clean and confident answer, and was wrong.
What we are correcting
The previous version of this page said the rollup table had never held a row and that live computation was the only mechanism. Both statements were untrue. We have not deleted the page or quietly edited the sentences, because a vendor who publishes its own limitations has to be equally willing to publish its own errors — otherwise the honesty is a marketing position rather than a practice.
The check that produced the wrong answer
Modern applications reach a database through a translation layer. You define a class that represents a table, and from then on you work with the class: the framework turns your instructions into database commands. This is standard, it is good practice, and it means the class name is a reliable handle on the table.
So the audit searched for the class name across the whole application. It appeared in exactly one place — the file that defines it. No other code mentioned it. The conclusion followed cleanly: if nothing refers to the class, nothing goes through it, and the table behind it is empty.
Every step of that reasoning is sound. The premise is not. The class is genuinely unused, and the table is written several thousand times a night — because the code that writes it does not go through the class at all. It addresses the table directly, by name, using the lower-level tool the same framework provides.
The search was for the handle. The work was being done without it. Nothing in the result set could have hinted at that, because the result set was correct.
And there is a good engineering reason for it, which is what makes the trap durable rather than sloppy. Writing several thousand rows one object at a time is slow and memory-hungry. The direct route inserts them in batches, and it can express "insert this, or update it if it is already there" as a single database operation. For a nightly aggregation job that is precisely the right choice.
So the strongest signal available — a class referenced nowhere — was produced by a decision that improved the code.
What is actually there
Six figures are rolled up, once a day, for each organization: goods received and goods issued as counts, the quantities moved in each direction, and the till's takings as both a value and a number of sales. A scheduled job runs in the small hours, holds a lock so two servers cannot duplicate the work, and writes one row per organization, per day, per figure.
The read path is where the design earns its keep, and it has three parts. They are worth setting out because most systems that precompute get at least one of them wrong.
Finished days are read from storage
A day that has closed cannot change by itself, so its figure is computed once and read thereafter. This is the whole point and it is what stops a four-year chart re-reading four years of transactions on every page load.
Today is never stored
Today is unfinished, and a stored partial is the most dangerous kind of number: it looks settled. A dashboard opened at nine in the morning would otherwise keep reporting nine o'clock's takings for the rest of the day. Today is aggregated fresh, every time, and appended to the stored history.
A day that was never built repairs itself on read
If the nightly job did not run, the missing days are recomputed and stored when somebody next looks — as a single query across the whole gap rather than one per day. A skipped run costs one slower page load instead of showing a silent zero.
That third part is the one that matters most, and it is the reason precomputed figures are usually not worth trusting. The standard failure is not that the aggregation job is wrong. It is that the job did not run, and a missing row is indistinguishable from a genuine zero. The chart draws a flat line through a week when the warehouse was busy, and nothing anywhere says so.
A system that treats an absent row as a question rather than as an answer removes that failure entirely. It is a small amount of code and it is the difference between a fast dashboard and a fast dashboard you can act on.
The part we got right, and it is smaller than it looked
One half of the original finding survives. There is an unused surface here — the translation class nobody calls. It is a real thing, it is inert, and leaving it in place is a decision rather than an oversight: it is the natural handle for this table the day somebody wants to work with a single row rather than a batch.
What was wrong was the inference drawn from it. An unused class was reported as an unused table, and a genuine but trivial observation became a false and consequential claim about how the product works.
That is the shape of most wrong statements about software. Not an invented fact — a real observation, extended one step further than it can carry.
How to check a claim like this, including ours
This is a buyer's problem as much as a vendor's. You are told a system does something, or does not do it, and you have no code to read. What you have instead is the ability to ask questions whose answers cannot be produced by a belief.
-
Ask what writes it, not what uses it
These are different questions and only the first one has a definite answer. "Nothing uses that" is a statement about a search; "this job writes it at this time" is a statement about the system. Ask for the second.
-
Ask what happens when the job does not run
Every scheduled task fails sooner or later. The answer separates a design from a hope: a system that notices a missing figure is engineered, and one that draws a zero is not.
-
Ask whether today is included, and how
The single most common defect in precomputed reporting is a partial day presented as a whole one. If the answer is vague, the number on the screen this afternoon is probably this morning's.
-
Then look at the screen twice, an hour apart
No access, no documentation, no trust required. If today's figure has not moved and the business has been trading, you have found the defect in the two minutes it took to look.
Four questions about any dashboard figure
Is this figure computed now or read from storage?
A good answer sounds like
A direct answer, and ideally a different one for today than for last month.
What it actually means
A single answer for both is the warning sign. Every well-built dashboard treats the unfinished day differently from the finished ones, and a vendor who has not thought about that has not thought about the problem.
What happens if last night's aggregation did not run?
A good answer sounds like
A description of a repair, or of an alert.
What it actually means
Ours recomputes the gap when somebody next looks. The unacceptable answer is silence, because silence means a zero on a chart, and a zero on a chart is a decision somebody will make wrongly.
Which figures are precomputed, exactly?
A good answer sounds like
A short list.
What it actually means
It should be short. Ours is six. A vendor claiming everything is precomputed is either running a much larger system than they are selling you, or has not distinguished a cached page from a stored metric.
How did you verify that, and when?
A good answer sounds like
A date and a method.
What it actually means
The question this whole page exists to justify. We answered it confidently and incorrectly in August; the method was the problem, not the care. Anybody can be wrong here, so what you are testing is whether they will find out.
The correction, in one line
Dashboard history here is precomputed nightly, finished days are read from storage, today is always live, and a day that was never built rebuilds itself the moment somebody looks. The previous version of this page said none of that was true. It was checked carefully, by the wrong method, and published — which is the single most useful thing on this page, because the same method is how most confident claims about software go wrong.
What AWRA OpsHub does today
- Six figures rolled up nightly per organization — goods received and issued as counts and as quantities, and till takings as both a value and a count — with the job holding a lock so two servers cannot double-count.
- Finished days read from storage and today always computed fresh, so a chart is fast without any figure on it being a partial presented as settled.
- Self-repair on read: a closed day with no stored figure is recomputed and saved when somebody next opens the screen, in one query across the whole gap.
- A backfill that can build an organization's entire history from its first transaction, rather than only the last few days.
- Exports in several formats, which remain the record of what a figure was on the day you published it.
More we can add to your workspace
- An as-at view for figures beyond the six, answering what any metric read on a stated past date.
- A stored series for financial and project figures, which are computed on read today.
- A visible marker on a chart where a day was repaired on read rather than built on schedule.
- An alert when a nightly aggregation is skipped, so the repair is noticed rather than only being absorbed.
- A version history on a report definition, so a certified report and the definition that produced it stay tied together.
Where we point you to a specialist
- We will keep publishing corrections on the page that carried the error, under the same address, rather than editing the sentences away. A vendor willing to name its own limits has to be equally willing to name its own mistakes, or the first practice is decoration.
- Deciding which figure a board pack should carry is your accountant's judgement and your auditor's. We supply the series and the date it was produced; we would not select the measure on your behalf.
- Computing the unfinished day fresh stays non-negotiable. We would rather pay for that query on every load than store a partial that reads as settled, and we would decline a request to cache today for speed.
A stored series for the financial and project figures, an alert when a nightly run is skipped, and an as-at view across all of them are each scoped work we can quote on.
Three, and the first is the one people actually feel
The mechanism already exists and is proven on six figures. Extending it is wiring rather than invention, which makes it unusually easy to scope.
The same rollup across finance and projects
Margin, receivables ageing and project burn stored on the same nightly cadence, with the same three rules — finished days stored, today live, gaps repaired. These are the figures people most often want as a trend and they are the ones still computed on read.
An alert when a nightly run is skipped
The repair-on-read is a safety net and it is currently a silent one, which means a scheduler that has been broken for a fortnight looks exactly like one that is working. A notification turns an absorbed failure into a known one.
As-at reporting across every stored figure
What did this number read on that date, answered from the stored series rather than by re-querying today's data. This is what turns "why does March disagree" from an argument into a lookup.
How it works: you describe the requirement, we return a written scope, timeline and cost, and once agreed it is built into your environment and maintained as part of the product. If a board pack has ever been questioned in your business, the third item is the one to raise.
Talk to us about reporting historyAsk your vendor how they checked
Not what the answer is — how they arrived at it, and when. We answered this question about our own product carefully, confidently and wrongly in August. The method was the failure, and it is the method you can actually test.
Talk to us about reportingFrequently asked questions
Are dashboard figures here stored or computed live?
Both, deliberately. Finished days are read from a stored nightly rollup; the current day is aggregated fresh every time the screen loads, because a stored figure for an unfinished day would look settled when it is not.
What happens if the nightly aggregation does not run?
The missing days are recomputed and stored the next time somebody opens the screen, as one query across the whole gap. The cost is a single slower page load rather than a chart showing zero for a week the warehouse was busy.
Can I reproduce a report exactly as it ran last month?
For the six rolled-up figures, the stored series holds what each day was. For anything else, the export you kept is the record — re-running it produces today's answer for last month's period, which differs wherever anything has since been corrected.
Why did this page previously say the opposite?
An internal audit searched for the name of the code object that represents the table and found it referenced nowhere, which is true. The table is written by a lower-level route that never names that object. The observation was correct and the conclusion drawn from it was not.