The first usage file a customer sends you is a demo. The fortieth one is the job. Somewhere between those two, column order shifts, someone adds a currency field, a vendor starts sending corrections with the same timestamp as the original row, and whatever mapping you hard-coded against file one quietly stops matching file forty.
A usage template is Sonic's answer to that drift: a saved, reusable translation from "however this customer's export is shaped" into "a metered event Sonic can bill." Built once, it has to survive every file after the first one — which means it has to be built defensively, not just correctly for today's sample.
The translation has three jobs, and they fail differently
Turning a raw row into a billable event means answering three questions, and each one has its own failure mode if you get it wrong:
Which customer does this row belong to? Get this wrong and you bill the right amount to the wrong account — a matching problem, usually caught fast because the wrong customer complains.
What does this row actually measure? Get this wrong — a unit conversion off by a factor, a currency field misread as a count — and every invoice downstream is wrong by the same silent multiplier, usually caught slow, at renewal, when someone finally reconciles a year of invoices against a year of raw exports.
Have I seen this exact row before? Get this wrong and a routine re-run — a retry after a timeout, a corrected re-export, an hourly sync that overlaps its own window — turns into a duplicate charge. This is the one that costs you a customer relationship, not just an adjustment invoice.
Most billing incidents trace back to the third question, because it's the one people assume the platform handles automatically. It doesn't, on purpose.
Why nothing should happen until you say so
The tempting design is to stage and validate a file the moment it's uploaded, so the operator sees results instantly. That convenience is exactly how partial, wrong, or duplicate data gets a foothold: a sample uploaded to check column headers gets treated as a live run, and now there's billable-looking data sitting in a system that assumes anything present is meant to be there.
Sonic keeps the boundary explicit instead. Attaching or previewing a file changes nothing on its own. A separate, deliberate action turns a mapping into a validated, billable pipeline — and until that happens, nothing downstream reads the file as real. The cost is one extra click. The benefit is that "I was just looking at the file" can never become "I accidentally billed the file."
The idempotency key is the part you can't get from the platform
Sonic doesn't guess what makes a row unique in your vendor's export — it can't, because that answer is different for every vendor. A payments processor's transaction ID is a safe key. A telecom CDR's (account, call start time) pair is usually safe. "Customer plus calendar day" is safe only if the vendor never sends more than one correction for the same day — a promise most vendors don't actually keep.
The wrong key doesn't fail loudly. It fails the third or fourth time you re-run the same file, when a correction with a new value but the same "unique" key either gets silently dropped (undercounting) or silently duplicated (overcounting) — and by then the file that exposed the bug has already been reprocessed and archived.
What changing the mapping does and doesn't do
Templates get edited constantly as vendors change their export format. The rule that matters here: changing a mapping changes how future files are read. It does not reach back and reinterpret events you already billed. That's a deliberate asymmetry — it means a mapping fix can't retroactively turn last month's correct invoice into this month's "corrected" one, which is the same immutability principle that keeps a sent invoice frozen once it's out the door.
Watch out for
- Test a new or changed mapping on a small window before pointing it at an hourly sync. A wrong transform scales as fast as your sync frequency.
- A "customer + date" key is a bet that the vendor never sends same-day corrections. Most vendors eventually do.
- Late-arriving usage lands on the next open invoice, not the one already sent. Immutability applies to usage lines the same way it applies to everything else.
- Seat data is not usage data wearing a different hat. Seat ingestion adds confirmation windows and snapshot semantics that don't transfer from a usage key design.
- The sample file you tuned the mapping against is not the file you'll get in production. Build the key for the messiest plausible export, not the clean one you were handed for the demo.