Order DataStore Caching — A new approach to optimize WooCommerce performance

To further improve order performance, as of WooCommerce 9.6, we will introduce a new feature gated option to enable caching of raw order data within the HPOS data store layer.

Enabling this option moves the persistent cache management for orders from the OrderCache class, which currently attempts to cache instances of the WC_Abstract_Order objects, to the OrdersTableDataStore and OrdersTableDataStoreMeta classes where raw data will now be cached.

This feature is in alpha testing as we assess the impact of backward compatibility. Any newly introduced interface methods for directly interacting with the data store cache may undergo significant changes during alpha testing. Therefore, defensive programming practices should be used for any early adoption that make direct use of the underlying cache methods.

Why is Order DataStore Caching being introduced?

The current implementation of OrderCache attempts to persistently cache WC_Abstract_Order objects. However, to prevent the unserializing of objects contained with an order that may not function as expected when unserialized, the serialization method override, WC_Data::__sleep(), was implemented early in the migration to the CRUD layer to only store the data object’s ID. This requires the object to rehydrate from the data store after being unserialized, resulting in additional overhead of extra database queries being required to retrieve sets of order objects.

Instead of modifying the current WC_Data serialization behavior, we chose to move the caching to the data layer of the data stores for the following reasons:

  1. The ability for WooCommerce extensions to extend and override the behavior of WC_Abstract_Order makes altering the current behavior of __sleep()/__wakeup() in a backward compatible way extremely difficult.
  2. It reduces the risk of caching a “dirty” object that doesn’t reflect the state of the database.
  3. It allows the data stores to more directly manage the cache of the data it controls.

What changes are included?

Order DataStore Caching includes the following changes:

Changes to OrderCache

The following change in behavior for OrderCache will only be active when Order DataStore Caching is enabled.

Because of hooks and filters, repeatedly creating new instances of the same order object as requested through calls to get_order(), like during checkout, can cause performance overhead even if the underlying data is cached. To reduce this overhead, the cache group that OrderCache uses is changed from orders to order_objects and the order_objects cache group is registered as non-persistent.

Changes to Order DataStores

The following changes in behavior for HPOS Order DataStores will only be active when Order DataStore Caching is enabled.

OrdersTableDataStore is responsible for hydrating orders with data from the HPOS order table.

  • [protected] ::get_order_data_for_ids() will first attempt to retrieve the data for each order ID from cache and only retrieve the data from the database when there is a cache miss.
  • [public] ::clear_cached_data() and [public] ::clear_all_cached_data() have been added to allow the clearing of cache when needed after a direct DB write. Note that these interfaces are internal and not guaranteed.

OrdersTableDataStoreMeta is responsible for hydrating order meta with data from the HPOS order meta table.

  • [public override] ::get_meta_data_for_object_ids() will first attempt to retrieve the data for each order ID from cache and only retrieve the data from the database when there is a cache miss.
  • [public] ::clear_cached_data() and [public] ::clear_all_cached_data() were added to allow the clearing of cache when needed after a direct DB write. Note that these interfaces are internal and not guaranteed.

Compatibility

Extensions that have fully migrated to using the CRUD layer of WooCommerce core to manipulate order data should have no concerns with compatibility. Compatibility with order data caching is only a concern if an extension:

  • Bypasses the CRUD layer by using direct database queries to manipulate order data.
  • Extend the internal Order DataStores (discouraged) in a way that bypasses cache invalidation triggers.
  • Relies on directly clearing the orders cache group to clear cached data for an order. Order data and meta will be stored with the orders_data and orders_meta cache groups accordingly, while order object caching will be in its own order_objects group.

We encourage all developers of extensions that interact with orders to test their integration with order data caching enabled early. Our plan is to roll out order data caching as a non-Alpha feature in release 9.7.

How to enable Order DataStore Caching

Because this feature is in Alpha stage, the enabling of the feature is further gated by a config constant. To access the option, you will first need to add the following to your wp-config.php.

define( 'WOOCOMMERCE_ENABLE_ALPHA_FEATURE_TESTING', true );

Once the constant is defined, HPOS Data Caching can be enabled in the WordPress Admin under WooCommerce > Setttings > Advanced > Features. There, you will have the option to enable order data caching in the data store.


2 responses to “Order DataStore Caching — A new approach to optimize WooCommerce performance”

  1. pacmanito Avatar

    “Bypasses the CRUD layer by using direct database queries to manipulate order data” – and what about WP functions?

    E.g. using update_post_meta for modifying some order items is considered a proper method or I should use $order_item-> update_metadata() to get full compatibility?

    1. prettyboymp Avatar
      prettyboymp

      E.g. using update_post_meta for modifying some order items is considered a proper method or I should use $order_item-> update_metadata() to get full compatibility?

      The cache handling of Order_Items is not modified with Order DataStore caching enabled. This only effects the cache handling around Orders directly.

      Continuing to only use update_post_meta() for Orders will continue to work as before if your site is using Compatibility Mode to synchronize between the posts and HPOS table. However, developers should migrate their code to use the CRUD interfaces as keeping compatibility mode active does add performance overhead for sites.

Leave a Reply

Your email address will not be published. Required fields are marked *