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. This 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 being based on IHandler and IPipeline, it is based on the 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 asynchronous pipeline available for invocation. The type parameters are the input and response types, respectively.

IAsyncPipeline<TIn, TWorkspace, TOut>

This creates base code pipelines. The intermediate TWorkspace type passes to each step, while the TOut is produced 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 base code and lets you alter them. You can inject new steps, remove base steps, and combine them to replace an existing step.

The order property used by legacy IPipeline is gone. The order of the steps returned by the IEnumerable is the order they are run, with steps targeted for extension located 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 native async support was impossible and performance profiling was 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. Introduction of the intermediate workspace type is useful for the future but is not currently used.

Can we use async code now?

The constraints around async are in place due to embedded dependencies on legacy code. 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 objects like IUnitOfWork to be lost in legacy code called 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, called v2. Since this introduces a large break, it allowed configuration for async in the future. The improved performance profiling capability also increased productivity during v2 development.

Future legacy-free code built around IAsyncPipeline can fully support native async.

How do I use Cart v2?

The Admin Console now has a setting called 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 final objects returned to the HTTP caller are the same 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, GetCart in the new namespace 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 methods returning a Task should be postfixed with Async, even though async is not yet ready due to mixed legacy code.

How do I migrate my Spire customizations to Cart v2?

The REST API is unchanged. If the .NET customizations your Spire customizations relied upon are converted, you do not need to make any Spire changes.

How was performance improved?

The primary method used to improve performance was to eliminate query loops–scenarios where a query was called multiple times in a loop with a single parameter. One example of this is the single item AddCartLine is gone in favor of 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, Configured Commerce releases throughout 2025 had improvements to Cart v1 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 pulled from the database. For example, retrieving a Product entity involves accessing more than 100 columns for every record regardless of what is actually needed by the storefront. 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 our 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 cart to be cleaned up on-demand instead of at the time an action was done that affects it.

Even though resolution of the biggest performance impediments for v2 may be out of reach for compatibility reasons, Optimizely may have opportunities for smaller wins.