A flash sale is the hardest thing a Magento store does: a marketing email lands in 80,000 inboxes at once and for twenty minutes the store sees more traffic than it does in a normal week, most of it heading for the same few products and then for checkout. This post follows a DevOps engineer preparing for one on MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic, using the auto-scalable Magento cluster package.

The store is a sneaker retailer we will call Kestrel Footwear, running the Auto-Scalable Magento Cluster: a Varnish load balancer, an auto-scaling layer of NGINX PHP application servers, a replicated MariaDB cluster, Redis nodes for sessions and cache, a search engine and shared media storage. The sale is a limited release of 400 pairs at 18:00 on a Thursday.

Where flash-sale traffic actually goes

The engineer's first job is to think about the request mix, because the three layers of the cluster absorb three different kinds of load. Most visitors hit the campaign landing page and the product page: cacheable, and Varnish should serve them without PHP. A smaller number add to cart, which needs PHP and Redis (the cart is in the session) but not much database. A few hundred reach checkout and place orders, which is the only path that writes to MariaDB. Sizing all three for the same peak is the classic mistake; the cluster lets each be sized for its own.

Layer one: make Varnish do the work

Magento's full-page cache with Varnish serves a cached page in under a millisecond of PHP time, because there is none. The engineer checks three things a week before the sale. First, that the campaign page and the release product page are cacheable, meaning no block on them is marked private or uncacheable by a badly written extension (Magento's X-Magento-Tags and the Varnish hit ratio confirm this). Second, that the pages are warm at 18:00: a small script requests them through the balancer every few minutes from 17:30 so the first real visitor gets a hit. Third, that Varnish's own container has headroom; it is a cache, so its cloudlet limit is about RAM, and the engineer raises it so the hot object set is never evicted.

On the night, the Varnish hit rate during the peak was above 95%. That number is what turned twelve times the traffic into roughly twice the PHP load.

Layer two: scale the PHP layer before the email, not after

The package pre-configures horizontal auto-scaling on the PHP layer, and the platform evaluates the triggers every minute against the layer's average load. That is fast, but a flash sale arrives in seconds, and a new PHP node takes a minute or two to provision and join the balancer. The engineer therefore does two things.

The PHP layer runs in stateful scaling mode, so each new node is a copy of the master node with the deployed Magento code, compiled DI and static content already in place. It joins the balancer automatically. At 18:04 the layer was at seven nodes; by 19:30 it was back to three, and the triggers returned it to two overnight.

TimeRequests/min at balancerVarnish hit ratePHP nodesOrders/min
17:451,20091%4 (pre-scaled)3
18:0114,80096%4 then 628
18:0416,20097%741
18:129,00095%719 (stock nearly gone)
19:301,90092%34

Layer three: sessions and the write path

Seven PHP nodes only work if a shopper's cart follows them from node to node, and in this cluster it does because Magento's sessions live in Redis, not on any PHP node's disk. The engineer confirms the session Redis node has a cloudlet limit large enough for tens of thousands of concurrent sessions (sessions are small; memory is rarely the limit) and that its maxmemory policy will not evict live carts. The cache Redis node is separate, which matters: a full-page-cache flush or a burst of cache writes never competes with sessions.

The database is the layer she scales least. Orders are the only writes, and 41 orders a minute is trivial for MariaDB. What she checks is the platform's ProxySQL entry point in front of the replicated cluster, which spreads reads across the nodes and sends writes to the primary, and the MariaDB nodes' cloudlet limits for the read burst from checkout's inventory checks. Vertical scaling gives those nodes CPU when the burst arrives and takes it back afterwards.

Inventory, the one thing that must not lie

Four hundred pairs must sell exactly four hundred times. Magento's inventory reservation model handles this in the database with row locks on the reservation table, and it holds under load as long as the database is not starved. The engineer runs a rehearsal on a cloned environment the day before: the same cluster, cloned in a few minutes, with a load tool placing 2,000 orders in three minutes against a product with 400 units. The clone sold 400 and rejected the rest. The rehearsal cost the hours the clone existed, which she deleted afterwards.

What the platform did that a fixed server could not

Nothing in this post required buying capacity in advance. The PHP layer grew by five nodes for ninety minutes and shrank again; the database nodes took extra cloudlets for the checkout burst and released them. Billing is per cloudlet-hour on what was used, so the sale cost Kestrel roughly what a normal Thursday costs plus a few dollars for the extra PHP nodes and the rehearsal clone. The alternative, a server sized for 18:04 every night, is what the store had before, and it still fell over.

Frequently Asked Questions

Why pre-scale manually if the triggers are automatic?

Triggers react to measured load over at least a minute, and a new node needs a minute or two to start. For a spike that arrives in seconds you want the first extra nodes already serving. Pre-scaling before a known event and letting the triggers handle the rest is the standard pattern; for unannounced spikes the triggers alone still respond within a few minutes.

Does a Varnish flush during the sale hurt?

Yes, briefly: every page becomes a PHP request until it is cached again. Avoid saving products, categories or CMS blocks during the sale window, since Magento invalidates the affected pages on save. If you must, do it before the warm-up script runs.

How does the checkout stay consistent across seven PHP nodes?

Sessions and quotes are shared through Redis and the database, so any node can serve any step of the checkout. The PHP nodes are interchangeable copies; nothing about a shopper is stored on a particular node.

Scale for the drop, not for the year

The Auto-Scalable Magento Cluster on MassiveGRID PaaS adds PHP nodes when the email lands and removes them when the stock is gone. Varnish, Redis, replicated MariaDB and shared storage in one click, billed per cloudlet-hour. Free 14-day trial.

Magento Cluster on MassiveGRID PaaS

Further Reading