WCF configuration default limits, concurrency and scalability

Often I need to enumerate to my customers all the main configuration parameters related to default limits, concurrency and scalability of WCF, thus I decided to keep truck of all those parameters and features in order to have a unique place for reference.

From a configuration point of view, WCF provides some parameters that influence the availability and scalability of solutions. These parameters are:

  • configuration/system.serviceModel/behaviors/serviceBehaviors/behavior/serviceThrottling/@maxConcurrentCalls: defines the maximum number of messages actively processed by all the service instances of a ServiceHost. The default value is 16. Calls in excess of the limit are queued.
  • configuration/system.serviceModel/behaviors/serviceBehaviors/behavior/serviceThrottling/@maxConcurrentInstances: defines the maximum number of service instances that can execute at the same time. The default value is Int32.MaxValue. Requests to create additional instances are queued and complete when a slot below the limit becomes available.
  • configuration/system.serviceModel/behaviors/serviceBehaviors/behavior/serviceThrottling/@maxConcurrentSessions: defines the maximum number of sessions that a ServiceHost instace can accept at one time. The default value is 10. The service will accept connections in excess of the limit, but only the channels below the limit are active (messages are read from the channel).

These configuration parameters can also be configured by code using the ServiceThrottlingBehavior configuration.

Another set of interesting configuration parameters are those related to the default limits of messages, serialization measures, etc. of the various bindings. Here are the main ones, with the default values for each of the main bindings:

 

Parameter Description basicHttpBinding
basicHttpContextBinding
netMsmqBinding netNamedPipeBinding netTcpBinding netTcpContextBinding webHttpBinding wsHttpBinding wsHttpContextBinding wsDualHttpBinding ws2007HttpBinding
maxBufferPoolSize An integer value that specifies the maximum amount of memory that is allocated for use by the manager of the message buffers that receive messages from the channel. The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 8 bytes. The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb). 
maxBufferSize  An integer value that specifies the maximum size, in bytes, of a buffer that stores messages while they are processed for an endpoint configured with this binding. This value cannot be less than the next maxReceivedMessageSize attribute. The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). Not Available The default is 65,536 bytes (64Kb).

The default is 65,536 bytes (64Kb). If the transferMode attribute equals to Buffered, this attribute should be equal to the maxReceivedMessageSize attribute value.

If the transferMode attribute equals to Streamed, this attribute cannot be more than the maxReceivedMessageSize attribute value, and should be at least the size of the headers.

The default is 65,536 bytes (64Kb). If the transferMode attribute equals to Buffered, this attribute should be equal to the maxReceivedMessageSize attribute value.

If the transferMode attribute equals to Streamed, this attribute cannot be more than the maxReceivedMessageSize attribute value, and should be at least the size of the headers.

The default is 524,288 bytes (512 * 1024 = 0x80000 = 512Kb).  Not Available Not Available Not Available Not Available
maxRetryCycles
An integer that indicates the number of retry cycles used by the poison-message detection feature. A message becomes a poison message when it fails all delivery attempts of all cycles.  Not Available Not Available The default is 2. Not Available Not Available Not Available Not Available Not Available Not Available Not Available Not Available
maxReceivedMessageSize A positive integer that defines the maximum message size, in bytes, including headers, for a message that can be received on a channel configured with this binding. The sender receives a SOAP fault if the message is too large for the receiver. The receiver drops the message and creates an entry of the event in the trace log. This bound on message size is intended to limit exposure to Denial of Service (DoS) attacks. The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). Increasing this value alone is not sufficient in ASP.NET compatible mode. You should also increase the value of httpRuntime. The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb). The default is 65,536 bytes (64Kb).
maxConnections

An integer that specifies the maximum number of outbound and inbound connections the service will create/accept. Incoming and outgoing connections are counted against a separate limit specified by this attribute.

Inbound connections in excess of the limit are queued until a space below the limit becomes available.

Outbound connections in excess of the limit are queued until a space below the limit becomes available.

Not Available Not Available Not Available The default is 10. The default is 10. The default is 10. Not Available Not Available Not Available Not Available Not Available
openTimeout A TimeSpan value that specifies the interval of time provided for an open operation to complete. This value should be greater than or equal to Zero.  The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute).
closeTimeout
A TimeSpan value that specifies the interval of time provided for a close operation to complete. This value should be greater than or equal to Zero. Not Available Not Available The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute).
receiveRetryCount
An integer that specifies the maximum number of times the queue manager should attempt to send a message before transferring it to the retry queue.
Not Available Not Available The default is 5. Not Available Not Available Not Available Not Available Not Available Not Available Not Available Not Available
receiveTimeout A TimeSpan value that specifies the interval of time provided for a receive operation to complete. This value should be greater than or equal to Zero. The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes).
sendTimeout A TimeSpan value that specifies the interval of time provided for a send operation to complete. This value should be greater than or equal to Zero.  The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute). The default is 00:01:00 (1 minute).
timeToLive  A TimeSpan value that specifies how long the messages are valid before they are expired and put into the dead-letter queue.  Not Available Not Available The default is 1.00:00:00.  Not Available Not Available Not Available Not Available Not Available Not Available Not Available Not Available
reliableSession/@inactivityTimeout

A TimeSpan that specifies the maximum duration the channel is going to allow the other communicating party not to send any messages before faulting the channel.

Activity on a channel is defined as receiving an application or infrastructure message. If no activity is detected for the time specified by this attribute, the session is aborted by the infrastructure and the channel faults. The reliable session is aborted.

Not Available Not Available Not Available Not Available The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). Not Available The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes). The default is 00:10:00 (10 minutes).
readerQuotas/@maxDepth A positive integer that specifies the maximum nested node depth per read.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32.  The default is 32. 
readerQuotas/@maxStringContentLength A positive integer that specifies the maximum characters allowed in XML element content. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192. The default is 8192.
readerQuotas/@maxArrayLength A positive integer that specifies the maximum allowed array length. 
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
The default is 16384.
readerQuotas/@maxBytesPerRead A positive integer that specifies the maximum allowed bytes returned per read. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096. The default is 4096.
readerQuotas/@maxNameTableCharCount A positive integer that specifies the maximum characters allowed in a table name. The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384.  The default is 16384. 

Sorry for the big table layout. Many of these parameters are taken "as they are" from the product documentation. The only thing I've done is to write them in a unique and common place, for further reference. The red values seem to be different (using .NET Reflector) from the MSDN documented values. I hope that I didn't make mistakes, otherwise please drop me a comment ... thanks.

One last set of configuration parameters that in general influence the scalability of a WCF solution are the InstanceContextMode and ConcurrencyMode properties of the ServiceBehavior. These parameters are configurable only within the service code, and not in XML configuration, because they relate to the runtime behavior of the service and the service developer should be aware of their values. The InstanceContextMode parameter determines how many instances of the service have to be created by the WCF runtime. The possible values are:

  • PerCall: a new InstanceContext object is created for each call.
  • PerSession: a new InstanceContext object is created for each session. If the channel does not create a session this value behaves as if it were PerCall.This is the default value.
  • Single: only one InstanceContext object is used for all incoming calls and is not recycled subsequent to the calls. If a service object does not exist, one is created.

The ConcurrencyMode property relates to the threading behavior of the service. In fact it defines how the service behaves related to multi-threaded scenarios. Here are the possible values:

  • Single: the service instance is single-threaded and does not accept reentrant calls. If the InstanceContextMode property is Single, and additional messages arrive while the instance services a call, these messages must wait until the service is available or until the messages time out. This is the default value.
  • Reentrant: the service instance is single-threaded and accepts reentrant calls. The reentrant service accepts calls when you call another service; it is therefore your responsibility to leave your object state consistent before callouts and you must confirm that operation-local data is valid after callouts. Note that the service instance is unlocked only by calling another service over a WCF channel. In this case, the called service can reenter the first service via a callback. If the first service is not reentrant, the sequence of calls results in a deadlock.
  • Multiple: the service instance is multi-threaded. No synchronization guarantees are made. Because other threads can change your service object at any time, you must handle synchronization and state consistency at all times.

In the following table you can see the matrix of available configurations and behaviors for InstanceContextMode and ConcurrencyMode:

  ConcurrencyMode.Single ConcurrencyMode.Reentrant ConcurrencyMode.Multiple
InstanceContextMode.Single Only one service instance is created and only one thread per-time accesses that instance. Requests are handled using a FIFO approach. Only one service instance is created and only one thread per-time accesses that instance. Requests are handled using a FIFO approach.

The single thread can leave the service code and come back later (for instance to make a callback or something like that).
Only one service instance is created and multiple threads can access that instance. Service code has to be synchronized in order to be thread safe.
InstanceContextMode.PerCall ConcurrencyMode does not matter because each call is handled by its own instance and thread ConcurrencyMode does not matter because each call is handled by its own instance and thread ConcurrencyMode does not matter because each call is handled by its own instance and thread
InstanceContextMode.PerSession (default) One service instance is created for each active session and only one thread for each session  accesses that per-session instance. Multiple concurrent requests related to the same session, and so to the same service instance, are handled using a FIFO approach. One service instance is created for each active session and only one thread for each session  accesses that per-session instance. Multiple concurrent requests related to the same session, and so to the same service instance, are handled using a FIFO approach.

The single thread can leave the service code and come back later (for instance to make a callback or something like that).
One service instance is created for each active session and multiple threads can access that instance. Service code has to be synchronized in order to be thread safe.

That's all. I hope you will enjoy this reference post.

3 Comments

  • Another good gotcha is the dataContractSerializer setting under

    Service Behaviors/MaxItemsInObjectGraph.

    Default is 65536 and I have seen this number being exceeded... don't ask why :)

  • keeping "truck" is important :)

  • Hi Paolo,

    Is it possible to configure the InstanceContextMode for a service through the app.config instead of having tp apply a [ServiceBehaviour] attribute?

    Fo eg. I'd like to specify InstanceContextMode.Single for a service using app.config. I don't think setting will achieve this effect

    Thanks

Comments have been disabled for this content.