The “Dirty Globals” Trap: Why Your Codeunit Is Leaking State Between Calls
A nightly batch job was producing incorrect financial totals. The issue was erratic. It didn’t happen every night, nor on every run. Just… sometimes.
The data looked like a phantom ledger was operating in the shadows. After three days of deep-dive transaction forensics, we found it. A global variable inside a SingleInstance = true codeunit was never being cleared between customer loops. Customer A’s balance was bleeding directly into Customer B’s calculations. The codeunit was holding onto state like a grudge, and the system was silently corrupting the financial trial balance.
⚠️ The Problem: SingleInstance Codeunits as Permanent Ledger Overlays
Most developers know SingleInstance = true means one instance per session. What they miss is the implication:
Global variables survive across procedure calls. For the entire session.
al// ❌ DANGEROUS – State bleeds between calls

🛠️ The Fix : Explicit State Management
For complex integrations—like Batch Payment Validation loop—global state should only be used intentionally to cache configuration data and reduce SQL round-trips. All transactional variables must be scoped locally so they evaporate safely when the procedure completes.

Why It Matters:
🎯 Data integrity – Dirty globals cause silent wrong calculations. No error. No warning. Just wrong data.
🎯 Reproducibility – Bugs only appear after the second call. Impossible to reproduce in isolated testing. Only surface in batch runs.
🎯 Session longevity – In SaaS, sessions can stay alive for hours. A variable set at 9 AM can corrupt a 4 PM batch if never reset.
☣️ The Trap
SingleInstance = true is not a design flaw – it’s a powerful optimization for caching config and avoiding repeated DB reads.
The trap is treating it like a stateless service when it isn’t.
The rule: Every global variable in a SingleInstance codeunit needs a documented answer to:
“When does this reset, and who is responsible for resetting it?”
If you can’t answer that, make it a local variable.
💡 The Bottom Line
SingleInstance codeunits are session-scoped singletons, not stateless utilities.
Global variables accumulate. Local variables evaporate.
Use globals for what should persist (config, cache).
Use locals for what shouldn’t (running totals, counters, flags per record).
Three days of debugging. One missing RunningTotal := 0.
Don’t let a missing reset ruin your Friday.