Correct a finalized period
This guide books what reached a finalized month after it closed. The correction meters the month again from the full event history with the pricing version the finalized run used, stores every non-zero difference as a delta, and renders one credit note per affected project. The finalized run stays as it is. What a correction is held against, and what it leaves the month with, is in billing period lifecycle and corrections.
Before you start
- A finalized month and the late events to book. Which resources took them is what detect late events reports.
- Both databases reachable from the machine you run the CLI on, and the counter sources file: a correction meters the month again, so it reads what run a period reads.
- Two empty directories for the exports, or two paths that do not exist yet.
tally-engineat the version the deployment runs, with its subcommands on the engine CLI page.- The engine settings page, which lists the variables this guide sets with their defaults.
Book the late events
Export the inputs of a metering pass.
TALLY_ENGINE_VM_URLis needed where the counter sources file declares a metricsql source:shexport TALLY_ENGINE_DB_URL='postgres://tally:password@db.internal:5432/tally_engine?sslmode=require' export TALLY_ENGINE_REPORTING_DB_URL='postgres://tally_engine:password@db.internal:5432/tally_reporting?sslmode=require' export TALLY_ENGINE_COUNTER_SOURCES=./counter-sources.yaml export TALLY_ENGINE_VM_URL=http://127.0.0.1:8428Meter the month again. The correction gets a run of its own and names the run it diffs against:
shtally-engine correct --period 2026-07textrun <correction id> completed as a correction of run <run id> for 2026-07 with pricing model 2026-03 metered <n> candidates into <n> usage records and <n> rated records <n> deltas in <k> credit notes warnings recorded in runs.stats: 0 metering, 0 counter, 0 attribution, 0 adjustment, 2 unpriced resource types, 0 unreadable fields, 0 unregistered projectsA correction that moved an adjustment as well prints
<n> deltas and <n> adjustment deltas in <k> credit noteson the third line.Close the correction. The period keeps naming the regular run that closed it, and the next correction diffs against this one:
shtally-engine finalize --period 2026-07 --run <correction id>textcorrection run <correction id> finalized for 2026-07Export the correction as a table and as documents, into a directory each:
shtally-engine export --run <correction id> --format csv --out ./2026-07/corrected tally-engine export --run <correction id> --format json --out ./2026-07/notestextrun <correction id> exported for 2026-07 as csv into ./2026-07/corrected wrote rated.csv with <n> rated records wrote deltas.csv with <m> deltas wrote kickbacks.csv with 0 kickback deltas run <correction id> exported for 2026-07 as json into ./2026-07/notes wrote run.json and <k> credit notes wrote kickbacks.json with 0 kickback deltasThe json export writes one
credit-note-*.jsonper affected project besiderun.json. What such a document holds is in credit notes.
Check the result
Read the third line of
correct.<n> deltas in <k> credit notesis the month moving, andno deltas: the finalized numbers of 2026-07 standis the re-metering arriving at what the finalized run already billed. The second answer still leaves a correction run behind, and finalizing it is what makes the next correction diff against it.Count the documents the json export wrote. There is one credit note per project a delta reached, and none for a project the correction did not move:
shls ./2026-07/notestextcredit-note-os-prod-eu1%2F9c4a1b2d3e4f5061728394a5b6c7d8e9.json kickbacks.json run.jsonAn
--outthat already holds files is refused, and nothing is written:text--out: ./2026-07/notes is not empty, and an export does not remove what an earlier one left there