Skip to main content
cdr_submit part 1 is the only per-message record of what was charged, and it is deleted once it passes the retention window. Without a summary that means no statement older than the window can ever be reissued, and the consumption side of every reconciliation disappears — so every aged account drifts into a discrepancy nothing can explain.

usage_daily is that summary

One row per account, per product, per day. Daily rather than monthly so that any period is a SUM over days — a calendar month, a quarter, an arbitrary from/to — forever, with no second derived table to disagree with it.
Run it nightly. Running it twice changes nothing that matters.

Billable figures are final; delivery figures are not

This is what makes the rollup safe to re-run. The rollup is idempotent and restates only the delivery columns. A finished day’s money is settled the moment the day ends.

A billing day is a local day

FIREFLO_BILLING_ZONE decides where a day starts, and it is read from app_config so the rollup and the panel agree.
On UTC, the last five and a half hours of an Indian customer’s evening land on the next day’s line. Every daily figure, every month boundary and every invoice is then off by that much traffic.Set the zone before the first rollup, not after — restating days already summarised means deleting and recomputing them.

The purge refuses to delete what nothing has summarised

If any day it would delete has no usage_daily row, it refuses the whole run and names the days. Not a warning and not a skip. Deleting an unsummarised day destroys the consumption record permanently, and that has to be structurally impossible rather than a matter of running things in the right order.
rollup is deliberately a separate command. A purge that quietly rolled up first would mean a rollup bug is discovered by the command that deletes the evidence.
FIREFLO_CDR_KEEP_DAYS sets the window, default 90.

Two windows, two purposes

cdr_interim is pruned on its own shorter window precisely because it answers a question about recent traffic: how fast a vendor reports, and whether it reports at all.

A retention policy is not optional

Call records contain addresses — they have to, because rating and dispute resolution need them. If message body recording is on, they contain content as well.
Set a retention policy deliberately rather than inheriting the default. Ninety days of destination numbers, and possibly of one-time passcodes, exists in every backup you take of that database.

A working order of operations

1

Set the billing zone before any traffic

It decides where every day boundary falls.
2

Roll up nightly

fireflo usage rollup --catch-up, on a schedule.
3

Verify the rollup covers the window before purging

The purge checks this itself and refuses — but knowing it passed is better than discovering it refused.
4

Purge on its own schedule

Behind FIREFLO_CDR_PURGE=true, which exists so it cannot happen by accident.

Call records

The three tables and what each column means.

Statements

Closing a period and issuing a bill.