The Problem: 70MB SAP Payloads in Memory

A common pattern when fetching SAP product data via OData is:

For small payloads this works fine. For SAP product catalogues with 50,000+ items, each response can exceed 70MB. Loading this entirely into a string allocates 70MB on the heap per call — and if you have 4 product categories running in parallel via Durable Functions fan-out, you're looking at 280MB+ of heap pressure per execution cycle.

The result: OutOfMemoryException, failed runs, and data gaps in Cosmos DB.

This is exactly the issue we solved during the BIOVIA OneLab Azure migration — a legacy WebJob fetching CG, USSTC, JMC and ON product categories from SAP OData endpoints.

The Solution: ResponseHeadersRead + JsonTextReader

The fix is to stream the response instead of buffering it. Two key changes:

1. Use HttpCompletionOption.ResponseHeadersRead

Instead of GetAsync(url) which buffers the full body, use:

2. Stream-deserialise with JsonTextReader

Use Newtonsoft Json.NET's JsonTextReader to deserialise directly from the stream:

Durable Functions Architecture

The overall orchestration pattern:

OData Filter Encoding

A frequent source of empty responses is incorrect OData filter encoding. The $filter parameter must be URL-encoded correctly — spaces as %20, single quotes escaped as %27. Validate your filter strings against the SAP Gateway test endpoint before deploying.

Results

After implementing streaming: zero out-of-memory failures, 99.97% successful job completion, peak memory reduced from 280MB+ to under 40MB per execution, and processing time reduced by approximately 35%.

Need help implementing this?

Neuaxis delivers enterprise integration solutions — Azure iPaaS, BizTalk, MuleSoft, Kafka and Neuron ESB.

Book a Free Consultation ↗