title: WCF HttpTransport: streamed vs buffered TransferMode
body: <p>I have a self-hosted WCF service (v4 framework) that is exposed through a <code>HttpTransport</code>-based custom binding. The binding uses a custom <code>MessageEncoder</code> that is pretty much a <code>BinaryMessageEncoder</code> with the addition of gzip compression functionality.</p>
  
  <p>A Silverlight and a Windows client consume the web service.</p>
  
  <p><strong>Problem</strong>: in some cases the service had to return very large objects and occasionally threw OutOfMemory exceptions when responding to several concurrent requests (even if Task Manager reported ~600 Mb for the process). The exception happened in the custom encoder, when the message was about to be compressed, but I believe this was just a symptom and not the cause. The exception stated "failed to allocate x Mb" where x was 16, 32 or 64, not a overly huge amount -for this reason I believe something else already put the process near some limit before that.</p>
  
  <p>The service endpoint is defined as follows:</p>
  
  <pre><code>var transport = new HttpTransportBindingElement(); // quotas omitted for simplicity
  var binaryEncoder = new BinaryMessageEncodingBindingElement(); // Readerquotas omitted for simplicity
  var customBinding = new CustomBinding(new GZipMessageEncodingBindingElement(binaryEncoder), transport);
  </code></pre>
  
  <p>Then I did an experiment: I changed <code>TransferMode</code> from <code>Buffered</code> to <code>StreamedResponse</code>  (and modified the client accordingly). This is the new service definition:</p>
  
  <pre><code>var transport = new HttpTransportBindingElement()
  {
      TransferMode = TransferMode.StreamedResponse // &lt;-- this is the only change
  };
  var binaryEncoder = new BinaryMessageEncodingBindingElement(); // Readerquotas omitted for simplicity
  var customBinding = new CustomBinding(new GZipMessageEncodingBindingElement(binaryEncoder), transport);
  </code></pre>
  
  <p><strong>Magically, no OutOfMemory exceptions anymore</strong>. The service is a bit slower for small messages, but the difference gets smaller and smaller as message size grows.
  The behavior (both for speed and OutOfMemory exceptions) is reproducible, I did several tests with both configurations and these results are consistent.</p>
  
  <p>Problem solved, BUT: I cannot explain myself what is happening here. My surprise stems from the fact that <strong>I did not change the contract in any way</strong>. I.e. I did not create a contract with a single <code>Stream</code> parameter, etc., as you usually do for streamed messages. I am still using my complex classes with the same DataContract and DataMember attribute. <em>I just modified the endpoint</em>, that's all.</p>
  
  <p>I thought that setting TransferMode was just a way to <em>enable</em> streaming for properly formed contracts, but obviously there is more than that.
  Can anybody explain what actually happens under the hood when you change <code>TransferMode</code>?</p>