Performance and robustness

Building resilient and efficient commerce workflows.

Ask about this Page
Copy for LLM
View as Markdown

After completing this page, you should be able to:

  • Explain how GraphQL reference expansion improves front-end performance for Custom Objects.

  • Describe the impact of the new cart preservation policy on data retention and analytics.

  • Identify the benefits of cross-cloud connectivity for API Extension reliability.

  • Understand the improvements made to customer security flows and store-specific error handling.

Data resilience: Cart and Customer management

Robustness often means ensuring that data remains consistent and useful even when related resources change. Two key updates in 2025 improved how the platform handles the relationship between Customers and Carts.

  • Cart preservation on Customer deletion: previously, deleting a Customer record often meant losing the associated Cart data. Now, Carts are preserved when a Customer is deleted. The Cart becomes unassociated, allowing businesses to maintain accurate historical data for tax reporting, inventory management, and abandoned cart analytics without needing to keep the personal data of the deleted user.
  • Refined error handling for Store-specific Carts: to improve the robustness of multi-store and B2B setups, commercetools introduced better error handling for store-specific carts. If a request involves a customer who does not belong to the specific store associated with a cart, the API now provides a clear, actionable error. This prevents "silent" logic failures and makes it easier for front-end developers to guide users back to the correct store context.

Infrastructure and Security: reliable connectivity

A robust architecture requires secure and low-latency communication between commercetools and your external logic.

  • Google Cloud cross-cloud connectivity: API Extensions are critical to business logic. In 2025, commercetools introduced Cross-cloud connectivity for Google Cloud. This allows extensions hosted on Google Cloud to communicate with commercetools more reliably and securely, reducing the risk of timeouts and connection failures that can occur when traffic traverses the public internet.
  • Hardened customer account flows: we've improved how email verification and password reset tokens are managed to support more secure login flows: password reset tokens are now valid for 24 hours by default (down from 24 days), older tokens for email verification or password reset can be invalidated when a new token is created, older tokens for email verification or password reset are invalidated when a token is successfully redeemed, an error is returned when attempting to redeem an expired email verification or password reset token, and additionally, if a token's validity is 60 minutes or less, the token is now included in the Message.payload to help you build better asynchronous flows.

Enhanced traceability: Audit Log expansion

Robustness isn't just about preventing errors, it's about having the visibility to understand why they happened. In 2025, we expanded the coverage of Change Types recorded in the Audit Log, moving beyond simple "resource updated" Messages to capture specific, high-intent actions.

What’s new in the Audit Trail?

The platform now records much more specific data points when changes occur. Key highlights include:

  • Detailed Customer and Business Unit changes: you can now track exactly which address type was modified (billing vs. shipping) and compare the "before and after" values when sensitive fields like email addresses or Customer Group assignments are updated.
  • Security-centric logging: critical security events, such as password changes (SetPasswordChange) and changes to address Custom Fields, are now explicitly logged. This allows security teams to pinpoint exactly when a credential or sensitive attribute was modified.
  • Inventory and pricing governance: for businesses managing high-scale catalogs, the Audit Log now tracks changes to inventory keys, cart quantity limits, and Standalone Prices. This ensures that any change affecting a product's "orderability" or cost is fully traceable to a specific user or API client.
  • Resource relationship tracking: new SetReferencesChange logs for Cart Discounts and Discount Codes allow you to see exactly how promotional rules are being linked or unlinked from other platform resources, providing clarity on complex marketing logic.

These granular audit enhancements transform logging from a passive record into a strategic tool for both technical and legal teams. By linking specific configuration changes directly to business outcomes, developers can perform rapid root-cause analysis on performance shifts, while security teams gain the verifiable "paper trail" required for SOC2 and GDPR compliance. Ultimately, this transparency removes "black box" uncertainty from the order lifecycle, ensuring every change—from pricing logic to shipping methods—is fully traceable and governed.

Query performance: GraphQL optimization

Performance in a headless environment is often measured by "chattiness"—how many API calls are required to render a page.

One of the most significant performance boosts for developers is the addition of Reference Expansion for Custom Objects in GraphQL. Custom Objects are often used to store complex data (like warranty info or extra metadata) that references other resources (like Products or Categories).
Previously, you would fetch a Custom Object, and if that Custom Object had any references to other resources, you had to make a second API call to get the details of those resources. Now, you can expand those references in a single GraphQL query. This reduces the number of network requests and significantly speeds up page load times for data-heavy components.
Example:
Let’s create a simple Custom Object containing a list of references to our favorite customers (feel free to use IDs of any customers in your project). To speed things up, we can do it directly using the HTTP API Playground in the Merchant Center. Navigate to Settings ➜ Developer Settings ➜ HTTP API Playground and select:
  • Request method: POST
  • Endpoint: Custom-objects
  • Command: Create or update CustomObject
  • Body:
Create a Custom Object that contains a list of references to favorite customersjson
{
  "container": "demo-data",
  "key": "favorite-customers",
  "value": {
    "customers": [
      {
        "typeId": "customer",
        "id": "46fbc1a6-fd3c-424c-bbf5-096ab5da0f21"
      },
      {
        "typeId": "customer",
        "id": "abcd0a05-e532-4673-9bd9-dd8e9545c24a"
      },
      {
        "typeId": "customer",
        "id": "0644172f-72ec-47f0-9784-23617f3f4a80"
      }
    ]
  }
}
Then, click Send.

Once we have our Custom Object created, let’s use the GraphQL API to see if we can expand the references within it:

Expand references with GraphQL
// Ensure all necessary imports are included and the API client is instantiated as demonstrated in the first example.

/**
 * GraphQL query to fetch favorite customers from a Custom Object
 *
 * This query:
 * - Retrieves a Custom Object from the "demo-data" container with key "favorite-customers"
 * - Expands the customer references to get full customer details
 * - Returns customer id, email, first name, and last name for each favorite customer
 */
const query = `
query fetchFavoriteCustomers {
  customObject(container: "demo-data", key: "favorite-customers") {
    referencedResources(expand: "customers[*]") {
      path
      objs {
        ... on Customer {
          id
          email
          firstName
          lastName
        }
      }
    }
  }
}
`;

/**
 * Fetches and displays favorite customers from Composable Commerce
 *
 * This function executes a GraphQL query to retrieve customer information
 * stored in a Custom Object and logs the results to the console.
 *
 * @returns Promise<void> - Resolves when the query completes
 * @throws Logs error to console if the GraphQL query fails
 */
async function getFavoriteCustomers(): Promise<void> {
  try {
    // Execute the GraphQL query via the Composable Commerce API
    const result = await apiRoot.graphql().post({ body: { query } }).execute();

    // Log the favorite customers data in formatted JSON
    console.log("Favorite customers:");
    console.log(JSON.stringify(result.body.data, null, 2));
  } catch (error) {
    console.error("Error executing GraphQL query:", error);
  }
}

// Execute the function to fetch and display favorite customers
await getFavoriteCustomers();

Favorite customers:

Resultjson
{
  "customObject" : {
    "referencedResources" : [ {
      "path" : "customers[*]",
      "objs" : [ {
        "id" : "46fbc1a6-fd3c-424c-bbf5-096ab5da0f21",
        "email" : "seb@example.de",
        "firstName" : "Sebastian",
        "lastName" : "Müller"
      }, {
        "id" : "abcd0a05-e532-4673-9bd9-dd8e9545c24a",
        "email" : "jen@example.de",
        "firstName" : "Jennifer",
        "lastName" : "Schmidt"
      }, {
        "id" : "0644172f-72ec-47f0-9784-23617f3f4a80",
        "email" : "jen@example.uk",
        "firstName" : "Jennifer",
        "lastName" : "Jones"
      } ]
    } ]
  }
}

There we go, thanks to this new feature, we managed to get additional information about our referenced customers and we managed to do it all using just one API request!

Summary

The 2025 updates to performance and robustness prioritize "fewer, better calls" and "safer data transitions." By optimizing GraphQL for Custom Objects, hardening infrastructure connectivity, and ensuring carts survive customer deletions, commercetools provides a more stable foundation for enterprise-grade commerce.

Test your knowledge