Writing this blog has been in my bucket list for a long time now... Thanks to a recent inquiry, finally, I had the opportunity to put my ideas into words.
While some of the best practices shared below are specific to C4C OData API, majority also apply to other OData APIs. Thus, I hope they will help some of you in building high-performing OData interfaces.
Furthermore, I would really appreciate it, if you could contribute to this blog with your comments by sharing your own tips and tricks. Thanks in advance for that.
With that here are a few best practices that can be used to optimize an SAP Sales and Service Cloud (C4C) OData interface for better throughput.
Reduced number of round-trips
This is achieved by using batch requests ($batch) with the optimum batch size. Considerations here are;
Number of requests in a change-set: All requests in a change-set are committed together. Hence, if one fails, all will be rolled back!
The higher the number of requests in a change-set, the higher will be the throughput. Maximum number of requests in a change-set cannot be higher than the number of requests in a batch. Hence, see batch size recommendations below for determining ideal number of requests in a change-set for your interface.
Quality of the data is critical as errors will require other requests with correct data to be reprocessed. Note that such a retry-logic will need be implemented by your interface!
Related data must be kept in the same change-set. E.g. Updating Opportunity header and Items. This ensures transactional consistency.
Batch size: Optimum batch size depends on several factors – object type, payload size, customization etc.. Optimum batch size for your interface can be determined by trying different values. Our recommendation is to start your tests with 10 requests per batch for deep inserts and 50 requests per batch for simple inserts or updates and determine the best batch size based on the actual throughput figures.
Parallelization of the requests
OData API can be consumed via parallel threads. Considerations:
A unique object record cannot be updated by two threads at the same time. Trying to do so will result in “record locked by user ...” errors.
To ensure system’s availability for all users, the number of parallel threads in an interface should be limited. Therefore, we recommend that in a tenant the number of parallel threads making API calls should be less than 10 (total for all interfaces running in parallel). Furthermore, if such an interface(s) will run for a long time, the total number of threads should even be smaller (<7).
Optimum number can be determined (by testing) based on the API, customizations in the tenant and the request details.
Optimizing individual requests
Create operations should use deep-inserts where possible.
Create calls should suppress create response so that it doesn't include created entity record where possible. This is achieved using odata-no-response-payload header.
Updates should be based on HTTP PATCH operation and include only changed fields - where possible.
HTTP GET operations should only fetch the data required using $select query option.
Use of $expand query option should be avoided as much as possible. If used, it should be complemented with a $select query option.
HTTP GET operations can further be optimized by preventing to return code-list descriptions. Therefore, whenever possible HTTP GET operations should make use the of the header odata-no-codedescs.
Server and/or Client based pagination can be used for speeding up queries.
Reading metadata (e.g. .../c4codataapi/$metadata) or the service document (e.g. .../c4codataapi/) for fetching CSRF token should be avoided as these calls are quite expensive due to the size of the response payload.