Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Cart v2 overview

How Cart v2 differs from Cart v1 in Optimizely Configured Commerce

Cart v2 in Optimizely Configured Commerce is the evolution of Cart v1. It introduces breaking changes to improve performance. The API seen by the public web APIs used by the storefront is identical, so (for example) Spire customizations are unchanged, but the .NET code is significantly different.

.NET internal workflow changes

The break from v1 occurs immediately. Instead of using IHandler and IPipeline, it uses IAsyncPipeline, which replaces both.

This interface has four variations:

  • IAsyncPipeline<TIn, TOut>
  • IAsyncPipeline<TIn, TWorkspace, TOut>
  • IAsyncPipelineExtension<TIn, TWorkspace>
  • IAsyncPipelineExtensionFinish<TWorkspace, TOut>

IAsyncPipeline<TIn, TOut>

Inject this interface to make an async pipeline available for invocation. The type parameters are the input and response types, respectively.

IAsyncPipeline<TIn, TWorkspace, TOut>

This creates base code pipelines. The system passes the intermediate TWorkspace type to each step, while the system produces TOut from the workspace at the end. TWorkspace and TOut are the same for all base implementations to ease migration, but Optimizely may use dedicated workspaces and response types for new pipelines in the future.

Extension codes should not need to use this directly.

IAsyncPipelineExtension<TIn, TWorkspace>

The extension code uses this to modify an existing IAsyncPipeline. It has a single method, Extend, which receives the original IEnumerable of steps from the base code and lets you alter them. You can inject new steps, remove base steps, and combine them to replace an existing step.

Legacy IPipeline no longer uses the order property. TheIEnumerable returns the steps in the order they are run. The system locates steps for extension by name rather than by number. It is similar to Spire's extensibility model.

IAsyncPipelineExtensionFinish<TWorkspace, TOut>

The extension code uses this to modify a workspace's finisher, the code that converts the intermediate workspace type to the final output type. Because all current Cart v2 pipelines use the same type for both, this may not be useful.

FAQs

Why was this created?

Optimizely did not want to continue using IHandler because Optimizely couod not implement native async support, and Optimizely found performance profiling difficult due to its use of call chaining. Every step counted the combined processing time of every following step, increasing the effort required to identify the origin of performance problems.

IPipeline did not have the chaining problem of IHandler, but it was incompatible with async code. Optimizely introduced the intermediate workspace type for future use, but it is not currently used.

Can we use async code now?

Embedded dependencies on legacy code impose constraints around async. Optimizely has observed that in .NET framework builds of Configured Commerce, attempting to use native async code (the C# async/await keywords) can cause legacy code to lose objects like IUnitOfWork later in the same overall request.

The cart touches nearly all functionality of Configured Commerce. Enabling native async requires a rewrite of the code, which Optimizely does not currently have the time to do. As a consequence, all base async code still forces it to run synchronously by attaching .GetAwaiter().GetResult() to the async method and returning Task.CompletedTask instead of using a native async function.

If we did not get async support, why bother with a new extension model?

The changes to improve cart performance necessitated a new internal API version, which Optimizely calls v2. Because this introduces a large break, it allows configuration for async in the future.

Future legacy-free code that uses IAsyncPipeline can fully support native async.

How do I use Cart v2?

The Admin Console now has a setting, Cart Version, with a v2 option. Only those with ISC\_System can access it, so you must work with Optimizely Support to enable it.

When using this setting, the .NET code routes to the IAsyncPipeline version of the cart instead of the legacy IHandler version, but the system returns the same final objects to the HTTP caller as before, avoiding the need to rework Spire customizations.

How do I migrate my .NET customizations to Cart v2?

The new code is within the namespace Insite.Cart.Services.Async. Optimizely intentionally re-used the same internal names to make migration a straightforward process. If you customized the legacy GetCartHandler or GetCart in the new namespace, it is the new location. Continuing that example, if you customized the CopyCustomPropertiesToResult step within GetCartHandler, the step within the new GetCart is the same place in the sequence with almost the same name. It is CopyCustomPropertiesToResultAsync as .NET convention is that you should postfix methods returning a Task with Async, even though async is not yet ready due to mixed legacy code.

How do I migrate my Spire customizations to Cart v2?

TThe REST API remains unchanged. If you convert the .NET customizations your Spire customizations relied upon, you do not need to make any Spire changes.

How was performance improved?

Optimizely primarily improved performance by eliminating query loops–scenarios where the system called a query multiple times in a loop with a single parameter. One example of this is that Optimizely replaced the single item AddCartLine with a bulk-optimized AddCartLines. This works well with a single item but should significantly outperform v1, where v1 AddCartLines called AddCartLine in a loop.

As part of optimization, Optimizely discovered opportunities to improve Cart v1 performance in a backward-compatible way. As a result, Optimizely improved Cart v1 in Configured Commerce releases throughout 2025 without any customer or partner effort. Before committing to a v2 conversion, you should re-test cart performance with 5.2.2508 or newer to see if the v1 improvements are enough.

Will Cart V2 continue to be improved?

With the release of v2, Optimizely is averse to breaking changes and would only do so with encouragement from partners. Currently, the primary performance constraint is the large entity objects retrieved from the database. For example, retrieving a Product entity involves accessing more than 100 columns for every record regardless of what the storefront actually needs. Entity framework performance degrades as the column count increases, and these large objects create major overhead. Using specialized types with fewer columns would proportionally improve performance but make those objects less flexible for creative usage by Optimizely partners.

Another challenge is that the GetCart process is not a read-only action. It spends time fixing the cart before returning it to the user. Any changes here could destabilize cart functionality that expected the system to clean up the cart on-demand instead of at the time an action occurred that affects it.

Even though Optimizely may not be able to resolve the biggest performance impediments for v2 for compatibility reasons, Optimizely may have opportunities for smaller wins.