
Last Monday a customer informed me of a problem in his e-commerce store: sometimes, when adding a product, two products appeared in the cart.
What at first seemed like a problem with a quick solution (some cache error, JavaScript, etc), ended up becoming a headache that I solved 100% on Friday.
Symptoms
The first thing was to reproduce the error. Indeed, although not always, on most occasions, when I entered the store from my main browser (Edge), when I hit add a product, two products appeared in the cart.
It was not a specific product, it happened with almost all of them, but not always.
In addition, the client informed me that it did not happen on the mobile (iPhone). It is always important to have as much information as possible (browser, device, operating system, etc.).
To make it more complicated, after several tests, I see that the problem does not occur in Firefox either.
So we narrow the problem to Chromium-based desktop browsers (Edge, Opera, Chrome, Vivaldi…).
The platform on which the website is hosted is a Vultr VPS withGridPane stack and Relay Business + Object Cache Pro and Cloudflare to manage different security rules, in addition to those of GridPane. With this stack, the WooCommerce runs very fast and can handle thousands of connections without hardly flinching.
Cloudflare’s security rules (series of three security articles from Cloudflare) stop about 3,000-5,000 daily intrusion attempts on this store.
But on a couple of occasions we had more “insistent” attempts, with about 3 million requests per day, which initially caused the web to take between 1 and 3 seconds longer to load. But, by implementing the right rule, they were all stopped at the DNS level before reaching the server and, therefore, without affecting the VPS performance in the least. Therefore, having Cloudflare working properly is of vital importance.
Search for the solution
Although I will not go into the details of all the tests performed, I will say that once the error had been reproduced, the only thing left to do was to fix it (obviously).
The first thing to note is that there are and were no JavaScript bugs in the browser console, nor any substantial differences in the headers between Chrome and Firefox.
While I was adding products to the cart I was watching live logs from my computer thanks to the multitail remote connection viewing the access and error logs in split console. Nothing remarkable appeared with any of the browsers.
After asking some Codeable colleagues for help, they suggested me to log the requests:

Said and done, I save add to cart requests if they come from my IP:
/**
* Add to cart logging for debugging purposes.
*
* @param string $cart_item_key Item key for current cart.
* @param int $product_id Id of the product.
* @param int $quantity Quantity of the product.
* @param int $variation_id Id of the variation.
* @param array $variation Variation data.
* @param array $cart_item_data Cart item data.
*
* @return void
*/
function cl_add_to_cart_logging( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
if ( '83.69.83.69' === $_SERVER['REMOTE_ADDR'] ) {
$log_file = fopen( ABSPATH . 'log_cart.txt', 'a' );
$log_data = 'Date: ' . date( 'Y-m-d H:i:s:u' ) . "\n";
$log_data .= 'IP: ' . $_SERVER['REMOTE_ADDR'] . "\n";
$log_data .= 'Cart Item Key: ' . $cart_item_key . "\n";
$log_data .= 'ID Product: ' . $product_id . "\n";
$log_data .= 'Quantity: ' . $quantity . "\n";
$log_data .= 'ID Variation: ' . $variation_id . "\n";
$log_data .= 'Variation Data: ' . print_r( $variation, true ) . "\n";
$log_data .= 'Product Data: ' . print_r( $cart_item_data, true ) . "\n";
$log_data .= '-----------------------------------------------------------' . "\n\n";
fwrite( $log_file, $log_data );
fclose( $log_file );
}
}
add_action( 'woocommerce_add_to_cart', 'cl_add_to_cart_logging', 10, 6 );
And then I start to see the content of log_cart.txt
through multitail and check that everything is correct, although duplicate requests are received in the same millisecond for the same product.
The next step is to duplicate the server with the web to a new VPS the same. All identical… but here the problem does not occur. And at this point it starts to be a bit weird.
As long as I do not reproduce the bug in this copy, I will not be able to make changes to fix it.
The first solution
But what looks the same, is not always the same. The copy made did not have the orange Cloudflare icon(proxied) activated, so… activated and the failure appears.
Well, here is the first solution. As long as the definitive cause is not found, even if it weighs on me, I disable the CF proxy on the live site, praying that there is not an attack, that although we are prepared at the server level, it is always a thousand times better with the CF protection.
And here I can start working more calmly. On the one hand, the live web is working correctly and on the other hand, I can make all kinds of changes in the copy without affecting the users.
In CF I disable all the security rules, but the error still appears. I activate the CF proxy and the products are almost always added in duplicate.
I go to WordPress and disable all plugins except WooCommerce, change the theme to a twenty twenty and at the server level I disable all caches and security rules. Nothing, the problem remains the same
The ultimate solution
Using the browser tools, I download the HAR(HTTP Archive) files from Edge and Firefox with and without CF proxy , analyze them along with the live requests and discover the following in the Chromium browsers:

In which you see an extra request that ends in a 503 error… that request seems to be the culprit of adding a new unit to the cart, duplicating the request. But in the type we see that it is prefetch.
If we put together the 503 error, typical of CF in some situations, the prefetch and the Speculation Rules API, and we take into account that they are not compatible among other browsers with Firefox… in addition to the culprit, we almost have a way to the solution.
Friday afternoon I had a trip of a couple of hours, in which I started looking for this information and I found out that recently, it had been Cloudflare’s anniversary week in which they usually release many new products: https://blog.cloudflare.com/birthday-week-2024-wrap-up/
And indeed, there was Speed Brain, a service that promises to be fantastic, but… that they activated by default to all the domains of the free option, despite being a service in beta phase:

The service among other things and very summarized, using the Speculation Rules API and the AI makes a request for the page on which we are going to click.
Although I was on my cell phone, here I was already 90% sure that Speed Brain was the culprit of this behavior and already looking forward to get to the computer to test it.
So it was, development web, disable the service and everything working correctly. Go to the live web, deactivate Speed Brain there and activate again the Cloudflare proxy and everything working as it did a few days ago and again secured by the CF proxy .
Conclusion
It was an adventure and a headache right at the beginning of the week on Monday. I am writing this late on Sunday, hoping that another such adventure will not arise tomorrow.
Many hours searching for the error and debugging, which would have cost the customer well over a thousand euros if he had to pay for the time and work developed. But in these moments is where the client who has contracted the maintenance services really sees its usefulness, since without paying anything more he sees the results and resolution of the problem.
At other times it pays for maintenance for months and it looks like there is no work (which there is always underlying work to keep things from failing), but here we really see the result of why it is worth it.
Cloudflare gives us 10 free services and every now and then they add new features, as it has been in this case or in Turnstile‘s new features, but sometimes, enabling these features by default, brings unwanted consequences.
P.S. By the way, if you need to disable the Speed Brain service on your Cloudflare, it is under Speed -> Optimization -> Content Optimization.
