Back to blog
Engineering Notes 6 min read

Posting rules that survive a real close

Five module blocks feeding one glowing conduit into a ledger slab carved with a T-account.

Every accounting system posts to the general ledger. The ones that survive a real month-end close are the ones that made posting a single, auditable path — not a helper that each module calls in its own slightly different way.

The rule that pays for itself

One function writes to the GL. Everything else — sales invoices, cash receipts, disbursements, journal vouchers — hands it a balanced set of lines and lets it decide nothing. The moment a second module is allowed to write its own entries, the two implementations start to disagree, and the disagreement only shows up as a trial balance that is out by a few centavos three weeks later.

What that buys you

  • Debits and credits are checked in exactly one place.
  • The fiscal period check happens once, so a closed period is genuinely closed.
  • Reversal is symmetrical, because there is only one shape to reverse.
  • The audit trail is a by-product rather than a feature someone remembered.
If you cannot point at the one function that writes to the ledger, you do not have a posting rule. You have a convention, and conventions drift.

Making it enforceable

A convention that lives in a code review is not enforceable. Put the balance check where the database can refuse the write:

-- Refuse an unbalanced batch outright.
SELECT batch_id
FROM   gl_details
GROUP  BY batch_id
HAVING SUM(debit) <> SUM(credit);

Run that as a guard before the batch is committed, not as a report someone reads on the fifth working day. The difference between the two is whether the error is a rejected save or a reconciliation.

All articles