Where the numbers come from: the aggregator and empty states
Every number on the **Margin & Cash** page comes from somewhere. This article is the technical companion to [Margin & Cash: how HQ reads network profitability](/help/hq-margin-cash-overview): it tr…
On this page
- What this article covers
- Where to find it
- Path 1: a member's own figures, via the nightly aggregator
- Why this needs a separate process at all
- What it reads, per member
- Writing it back: encrypted evidence under the group's own key
- Schedule and freshness
- The three empty states this path drives
- Path 2: peer and industry comparisons, via the anonymized fact layer
- A different source, computed a different way
- The rest-of-industry cohort is restricted, not the whole database
- The anonymity floor and the confidence ladder
- The dollar-gap figure specifically
- The empty states this path drives
- Putting the two paths together
- What never appears on this page, either path
- Best-practice example
- Related help articles
- Data sources
What this article covers
Every number on the Margin & Cash page comes from somewhere. This article is the technical companion to Margin & Cash: how HQ reads network profitability: it traces each figure back to its source, explains the nightly process that computes it, and explains exactly why a row sometimes reads a plain sentence instead of a tile. If you've ever wondered why a member you know has healthy financials still shows "Margin Pending," or why the whole page looked empty the morning after you added a new group, this is the article that answers it.
Two different pipelines feed this page, and they draw on different data:
- Each member's own figures (margin percentage, cash-runway days, days-to-pay, and their position inside the group) are computed once a night by a scheduled aggregator process and written into an encrypted store HQ reads from. This is the sanctioned, narrow bridge between a member's own operating data and anything HQ's application server can see.
- Peer and industry comparisons (the network's percentile against the rest of the industry, the Cost Ratios vs Industry tiles, and the dollar-gap figure on the margin tiles) are computed live, on every page load, from a fully anonymized layer that never carries a member's identity at all.
Both paths respect the same rule: HQ's application server has no path to a member's raw invoices, bank balance, or P&L. What it reads is always a derived figure, computed elsewhere, by a process that is allowed to see the underlying data because it isn't HQ's server.
Note
This article is about mechanics: what computes what, and why a row is sometimes empty. For what each tile and column MEANS and how to act on it, read the Margin & Cash overview first.
Where to find it
Open Margin & Cash from the HQ sidebar, in the Intelligence group, or go directly to hq.verinode.ai/margin-cash. Everything described here feeds the hero panel, the Below Margin / Cash Runway Alerts / Top Margin rows, and the Cost Ratios vs Industry row on that page.
Path 1: a member's own figures, via the nightly aggregator
Why this needs a separate process at all
Verinode's multi-schema design keeps a member's business data (pii.*, the schema that holds jobs, invoices, and financial line items) walled off from core.*, the schema HQ's application server queries. HQ's server role has no grant into pii.* at all. That's deliberate: it's the technical form of the promise that franchisees own their data and HQ never sees a single member's private books.
But HQ still needs to know, at a network level, who's under cash pressure and who's ahead on margin. Something has to bridge the two schemas, and that something is a scheduled server-side job (internally, the aggregator cron) that runs with the elevated access it needs to read across the whole network's operating data, compute derived figures for each member, and write back only the derived result. It never writes a raw dollar figure, an invoice, or a bank balance into anything HQ's server can query. It writes a margin percentage, a runway-day count, a days-to-pay average, and a position label. That's the entire bridge, and it's the only one.
What it reads, per member
For every active member in your group's directory, the aggregator computes:
- Gross margin percentage: from that member's own trailing financial totals (revenue and cost of goods sold).
- Cash-runway days: the same runway forecast a member sees on their own IQ Cash Flow view (see Cash flow and cash runway), computed member-by-member.
- Days-to-pay: the average gap between billing and payment across that member's own jobs billed and paid in roughly the trailing 90 days.
- Margin position: where that member's margin sits relative to the rest of the group, banded as below the group's own bottom quartile, between the quartiles, or above the group's own top quartile. This banding is computed against your OWN group's members only, not against the rest of the industry, which is why the label on the page reads "Bottom Quarter" / "Top Quarter" rather than an industry percentile.
None of this touches the anonymized intelligence layer described in Path 2 below. It's a direct, member-by-member computation from that member's own operating data, run by the one process trusted to see it.
Writing it back: encrypted evidence under the group's own key
The aggregator doesn't write these figures as plain columns HQ's server can browse freely. It writes them into a single JSON payload, keyed by your group and the day's snapshot date, in the network data. That payload holds every member's figures for that snapshot, plus the network-wide runway bucket counts described below.
Before that payload is stored, the aggregator encrypts it under your group's own shared encryption key (a key wrapped separately for your group and unwrapped through Verinode's key-management layer at read and write time, never a shared platform-wide secret). The encrypted form lands in an evidence_ciphertext column alongside a same-shape plaintext the aggregate column, kept during the platform's rollout window as a fallback.
When the Margin & Cash page loads, it asks for the most recent snapshot row for your group and decodes it: it tries the ciphertext first, unwrapping your group's key and decrypting; if that fails for any reason (no key provisioned yet, a decrypt error), it falls back to the plaintext copy so the page still renders. Either path produces the exact same JSON shape, so what you see on the page never depends on which path resolved.
Schedule and freshness
The aggregator runs on a nightly schedule, sweeping every group in the network. Because a network can have many groups and each member's runway forecast takes a few database calls, a single run checkpoints its progress and can resume mid-sweep on the next scheduled invocation rather than silently dropping the tail of a long member list. In practice this means the figures on your page are as fresh as last night's completed run for your group, not live at the moment you load the page. A member who updates their cash balance this afternoon shows their new runway figure after tonight's run picks it up, not immediately.
The three empty states this path drives
- A member tile reads "Margin Pending" or "Runway Pending": that specific member has no margin (or runway) figure in the latest snapshot yet, most often because they haven't reported enough financial data on their own account for the aggregator to compute one, or the aggregator hasn't run since they connected it.
- The whole page's member rows and the runway bucket counts read zero, with subtext like "Network margins will appear as members share their financial data": the aggregator has never completed a snapshot for your group at all, most commonly a brand-new group. Every member falls into a "not yet on file" state that isn't a numbered bucket, it's just the gap between your roster's total and the three real bucket counts.
- A single member is missing from Below Margin, Top Margin, and Cash Runway Alerts entirely, without any error: that member's figure is null for whichever metric drives that row, so they don't qualify for any quartile or alert list on that basis. They still appear in the directory-driven Franchisees roster; they just don't have an opinion to render on this page yet.
None of these are broken states. They resolve themselves as members connect data and the next nightly run completes; there is no action to take from this page to "fix" them.
Path 2: peer and industry comparisons, via the anonymized fact layer
A different source, computed a different way
The figures that compare your network against the rest of the industry, the network's percentile on Network Median Margin, the Cost Ratios vs Industry tiles, and the "vs peer" dollar-gap figure on the Below Margin and Top Margin tiles, do not come from the encrypted evidence store described above. They're computed live, on every page load, from Verinode's anonymized intelligence layer: a set of tables holding contributed operating facts (financial ratios, job-level figures, scores) keyed by a one-way cryptographic hash of the operator, not by the operator's identity.
Concretely: HQ's query code takes each member's operator ID, runs it through the same one-way hash function Verinode's anonymization pipeline uses everywhere, and joins against the anonymized fact tables on that hash. There is no reverse path from the hash back to an identity inside this code; the hash is one-directional by construction. HQ's queries can tell that "this hash's most recent gross-margin figure is 34%," never whose business that hash belongs to, if it isn't already a member of your own group.
For your own group's members, HQ already knows the identity, so hashing your own members back to their names for the group side of a comparison is just an internal lookup. The anonymity boundary is about the OTHER side of the comparison: the "rest of industry" figures never resolve to a specific outside business anywhere in this code path.
The rest-of-industry cohort is restricted, not the whole database
The "Industry" or "Rest" comparison isn't a raw pull of every row in the anonymized tables. It's restricted to a maintained allow-list of operators who have opted into and matured into benchmark eligibility, and further split so a real network is only ever compared against real peer data, never against demo fixtures, and vice versa. If that eligibility check can't be read for any reason, the comparison is treated as empty rather than falling back to an unfiltered pool, so a failure never leaks a broader, less-controlled comparison set by accident.
The anonymity floor and the confidence ladder
Before any percentile or delta renders, Verinode checks that enough distinct businesses back BOTH sides of the comparison, your group's side and the rest-of-industry side. If either side doesn't clear that bar, the percentile and the delta are withheld entirely rather than shown next to too few contributors to protect. You'll never see the actual head-count of that floor anywhere in the product; what you see instead is a confidence label that climbs as more data arrives: Awaiting Data, Early Signal, Trending, Observed, and Verified. That label is a confidence signal for how much data backs the comparison, not a toggle anyone on your team can flip, and it is a separate check from the anonymity floor itself: a comparison can clear the anonymity floor and still show a low-confidence label while more data accumulates on either side.
Cost-ratio comparisons carry a higher bar than the group's own margin comparison, because a cost ratio is computed from the normalized-P&L plane, a more identifying figure than a single percentage. That's a qualitative difference, not a number this article states, and it's why you may sometimes see Network Median Margin resolve to a real percentile while a specific cost-ratio tile still reads "Awaiting Data" for the same group.
The dollar-gap figure specifically
The "vs peer" dollar amount you see on Below Margin and Top Margin tiles (for example, "-$38k/yr vs peer") is computed fresh on page load by combining two anonymized-layer reads: the eligible rest-of-industry median margin (the same percentile math described above) and that member's own estimated annualized revenue, derived from their most recent anonymized financial-period record (employee count times revenue-per-employee, prorated to a year). The gap is (that member's margin minus the network's peer-median margin), turned into a fraction of revenue, multiplied by that estimated annual revenue. It's null whenever either half is missing, either because the member has no margin figure yet (Path 1's problem) or because Verinode hasn't yet estimated their annualized revenue from the anonymized layer (Path 2's problem). Either gap can be the blocker, and the tile doesn't distinguish which one for you, it just shows no dollar figure until both resolve.
The empty states this path drives
- A margin or cost-ratio tile shows a coverage label instead of a percentile or delta, most often Awaiting Data: not enough eligible peer businesses have contributed that figure yet, on your side, the rest-of-industry side, or both.
- A tile's meta line reads a bare member count instead of a delta (for example, a coverage count in place of "+3.0% vs Industry"): the anonymity floor isn't cleared for that specific metric yet, so Verinode is showing you how much data exists without showing a comparison it can't yet back.
- A member's dollar-gap figure is missing even though their margin percentage shows fine: their estimated annualized revenue hasn't resolved from the anonymized layer, or the network peer-median for that metric hasn't cleared its own anonymity floor yet.
Putting the two paths together
A single tile on this page can pull from both paths at once. Take a Below Margin tile: the member's location name, gross margin, and cash-runway day count come from Path 1, the nightly aggregator's encrypted evidence, computed directly from that one member's own data. The dollar-gap figure beside it comes from Path 2, computed live from the anonymized peer layer. That's why it's possible to see a member's own margin and runway resolve cleanly while their dollar-gap figure is still blank: the two numbers clear their bars independently, on different schedules, from different sources.
What never appears on this page, either path
Neither pipeline ever surfaces a member's exact dollar figures, an invoice, a bank balance, or a line-item P&L. Path 1 writes derived figures (a percentage, a day count, a position label) computed by a process with narrow, audited access, never the underlying ledger. Path 2 never resolves an outside business's identity at all, only a hash. See What HQ sees: the network privacy boundary for the full statement of that boundary across every HQ surface, and Coverage labels and the anonymity floor for the confidence ladder used here and on Benchmarks.
Best-practice example
Say you open Margin & Cash the morning after adding three new members to your group. The hero reads "Network margins will appear as members share their financial data," and all three of the new members show "Margin Pending" on their tiles, because tonight's aggregator run hasn't happened yet and their own accounts don't have enough financial data connected for it to compute a figure regardless. A week later, after two of the three have connected their financials and the aggregator has run several nights in a row, their tiles resolve to real margin and runway figures, and one of them shows up in Below Margin with a dollar-gap figure once their estimated annualized revenue clears from the anonymized layer. The third member, who still hasn't connected financial data, keeps showing "Margin Pending," not because anything is broken, but because Path 1 has nothing to compute yet for that one account.
Related help articles
- Margin & Cash: how HQ reads network profitability
- Cash runway distribution: under 30 / 30–60 / 60+ day buckets
- Below Margin and the intervention candidate list
- Cash Runway Alerts
- Top Margin: the network's recognition list
- The gap-in-dollars figure: margin position translated to dollars
- What HQ sees: the network privacy boundary
- Coverage labels and the anonymity floor
- HQ Benchmarks
- HQ Overview
- Network Health
Data sources
Data sources
- 1.Nightly aggregator snapshots of member margin, runway, and days-to-pay (the network data, encrypted under your group's own key). Verinode network aggregate store.
- 2.Each member's own financial and cash data, read only by the aggregator process, never by HQ's application server. Your franchise network's members.
- 3.Anonymized industry-wide financial and cost-ratio figures, keyed by a one-way hash of the operator. Verinode anonymized intelligence layer.
- 4.Benchmark-eligibility allow-list (real vs. demo, matured contributors only). Verinode network intelligence layer.