Xumulus Logo
Engineering

Magento 2 and AJAX with Optimistic Session Locking

Author

Dan Kozlowski

Date Published

While working on an optimization project, our team traced a significant Magento 2 performance problem back to PHP sessions and how Magento 2 handles concurrent AJAX requests.

The problem

In NewRelic we saw the /customer/section/load endpoint — the service that refreshes cart and other private data over AJAX — being invoked many times on a single page and running slowly. The culprit wasn’t Redis itself; it was Magento 2’s session locking.

How optimistic session locking works

Magento 2’s session read() uses an “optimistic” locking pattern — it assumes most requests won’t conflict. Each session lock is incremented so only one process can hold the lock at a time. That logic was designed for a world where a PHP request came from a single HTTP request.

Why AJAX breaks the model

Magento 2 leans on AJAX to work around full-page cache for private data. But when a single page fires five to ten AJAX requests at once, each one has to wait to obtain the read lock, complete its read, and release it before the next can proceed. The result is a sequential waterfall instead of parallel execution — exactly the slowness visible in monitoring.

What to do about it

One option is to add cache headers to AJAX endpoints that don’t need real-time data, so they aren’t re-fetched on every page. Colin Mollenhour’s Redis module added read-only support for Magento controllers as another avenue, though it wasn’t in Magento core at the time of writing. The key takeaway: watch concurrent locking on /customer/section/load when diagnosing Magento 2 AJAX performance.