The “Blob Field” Memory Sink: Why Implicit Stream Buffering Bloats NST Memory
A nightly job was processing thousands of vendor PDF invoices. Halfway through, the job queue crashed with out of memory errors, destabilizing the middle tier.
The hidden culprit? Retrieving MediaSet/Blob fields inside iterative loops. Each fetch silently allocates unmanaged buffer memory on the NST. Those allocations don’t release until the session ends, turning a clean routine into a creeping memory leak.
⚠️ The Problem: The implicit Blob fetch overhead
When you call Rec.CalcFields(“Attachment BLOB”) inside a record loop, the Business Central Service Tier fetches the complete binary payload from SQL Server into NST RAM.
If you iterate through 5,000 document records and retrieve binary streams without explicitly clearing the variable scope or managing stream lifetimes, the runtime holds onto those heap allocations. In a high-volume batch job or SaaS environment, this implicit memory accumulation leads to severe GC pressure, worker process recycling, and sudden job queue crashes.
🛠️ The Fix: Instream disposal and isolated stream scoping
Never hold binary payloads on a stateful record buffer across loop iterations. Wrap stream extraction inside short-lived local procedure scopes or explicitly instantiate temporary BLOB buffers (Codeunit “Temp Blob”) that flush memory as soon as the stream is processed.
Pair this with explicit field selection (SetLoadFields) to ensure non-essential BLOB or Media fields are completely excluded from initial SQL record fetch pipelines.


Technical Groundings:
➡️ Saas Available: Yes.
➡️ Runtime/Upgrade: Runtime.
➡️ Bypasses Triggers: Yes, stream operations on Temp Blob codeunits work purely in Middle Tier RAM without triggering database schema handlers.
Why It Matters
✅ Zero NST Heap Leaks: Keeps Middle Tier RAM usage flat across massive dataset loops by letting local stack frames handle garbage collection.
✅ Surgical SQL Reads: SetLoadFields prevents SQL Server from streaming high-cost binary payloads until the exact moment they are needed.
Resilient Job Queues: Eliminates out-of-memory process crashes during heavy overnight document parsing or PDF generation runs.
☣️ The Trap:
Avoid passing InStream variables as global codeunit state, streams tied to global variables remain pinned in memory for the entire life of the codeunit execution.
💡The Bottom Line: Isolate
Binary streams are heavy. Don’t let your record loops carry BLOB payloads across thousands of iterations, isolate stream scope and keep your Middle Tier fast and light.