Achieving Session affinity in CCv2

Nuray Fahri
3 min readJan 5, 2023

In CCv2 backend is running on multiple nodes which means that requests from our JS Storefront(Spartacus, React or any other) can hit different nodes each time if we do not configure session affinity(sticky session). Once session affinity is achieved same server behind API endpoint will be used for all subsesquent requests for the same session.

This is important for the performance improvement as without session affinity there are unnecessary resources consumed. In one of our products it was mandatory to have it as we have EhCache configured to keep some data and we had to make sure that all requests hit the same node to have consistency for the user.

CCv2 ROUTE Cookie

To achieve this CCv2 exposes response cookie — ROUTE which indicates the node that was used to process the first API request. After the response from first request once we add the ROUTE cookie to the next one, it will be handled by the same server.

Response from the first call:

Next request:

How we can leverage the ROUTE cookie?

To leverage the ROUTE cookie in CCv2 we:

  1. Should use withCredentials: true in the http request to enable using credentials such as cookies in our case.

How to achieve it in Spartacus?

In Spartacus we can achieve this with adding useWithCredentials: true in our enviroment.ts:

export const environment = {
production: false,
backend: {
occ: {
baseUrl:
'https://api.c4oemlbtqr-ccbmanage1-d1-public.model-t.cc.commerce.ondemand.com',
useWithCredentials: true
},
},
};

This was done using interceptor, you can check the commit: https://github.com/SAP/spartacus/pull/7115/commits/263624cac20b8b74d7ce1d9a0894d09a9b1d377d

How we did it in React?

Implemented it the same way, we just have:

  • RestClient — used to invoke Service API calls for the requested methods.
  • RestHelper — invoke the actual Service API calls for all the request methods.
  • RestConfig — to get the required request configuration for all the requests. And we added withCredentials here.
/**
* This class is to invoke the actual Service API calls for all the request methods.
*/
export default class RestHelper {
static invoke = (context, config, method) => {
const apiUrl = getApiUrl(context, config);
let response = {};
const requestConfig = getRequestConfig(getApiConfig(config), method, apiUrl);
return axios(requestConfig)
.then(response => {
response = { ...response, isSuccess: true };
return response;
})
.catch(error => {
response = { ...error.response, isSuccess: false };
return response;
});
};
}
export const getRequestConfig = (config, method, url) => {
const { baseURL, headers, params, data, responseType } = config;
const requestConfig = {
// `url` is the server URL that will be used for the request
url,

// `method` is the request method to be used when making the request
method: method || REQUEST_METHODS.GET, // default

// `baseURL` will be prepended to `url` unless `url` is absolute.
baseURL,

// `headers` are custom headers to be sent
headers,

// `params` are the URL parameters to be sent with the request
// Must be a plain object or a URLSearchParams object
params,

withCredentials: true
};

return requestConfig;
};

2. Should configure the SAP Commerce(Hybris) Cloud backend with one more CORS Filter Allow-Origin-With-Credentials:true, so cookies can pass the filter.

  • In SAP Commerce(Hybris) backend we can do it using the properties:
corsfilter.ycommercewebservices.allowCredentials = true

or

corsfilter.commercewebservices.allowCredentials = true

depending on which web service extension we use.

Same configuration for backend can be done directly on CCv2 side via support ticket.

--

--