skills/infrastructure-performance/flash-sale-scaling/SKILL.md
Prepare for Black Friday and flash sales with auto-scaling, queue-based order processing, and circuit breakers to prevent site outages
npx skillsauth add finsilabs/awesome-ecommerce-skills flash-sale-scalingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Flash sales and product drops generate traffic spikes 50–100× normal load, arriving within seconds of sale start. Without preparation, the checkout service collapses, inventory oversells, and customers see error pages. This skill covers the infrastructure patterns needed to handle extreme traffic: pre-warming, queue-based order intake with back-pressure, Redis-based atomic inventory reservation, and circuit breakers that degrade gracefully under load.
| Platform | Flash Sale Scaling Strategy | Key Actions | |----------|---------------------------|------------| | Shopify | Shopify scales automatically — no infrastructure work needed | Focus on theme speed (cache pages, optimize images), enable Shopify's queue page for high-demand launches, use Launchpad (Shopify Plus) to schedule and automate the sale | | WooCommerce | You own the server — significant prep required | Upgrade to a scalable host (Cloudways, Kinsta, WP Engine), enable Redis Object Cache + WP Rocket page cache, configure Cloudflare, run load tests 1–2 weeks before | | BigCommerce | BigCommerce scales automatically | Use BigCommerce's flash sale feature (preview: shows estimated wait time); focus on catalog readiness and theme performance | | Custom / Headless | Full infrastructure control needed | Apply all patterns below: pre-warm scaling, Redis inventory, queue-based checkout, circuit breakers |
Shopify handles scaling automatically and can handle virtually any traffic spike. Your prep work is:
Enable Shopify's high-demand checkout queue (Shopify Plus):
Use Launchpad (Shopify Plus) for sale scheduling:
Pre-test your store performance (all Shopify plans):
Notify Shopify support before major launches (Shopify Plus):
WooCommerce requires significant infrastructure work before a high-traffic event:
Hosting upgrade (most critical):
Cache stack:
Inventory oversell prevention:
Load test before the sale:
Pre-warm infrastructure (run 30 minutes before sale start):
# Kubernetes: scale checkout deployment up before sale
kubectl scale deployment checkout-service --replicas=50
# Or schedule automatic scaling with a CronJob
# See the CronJob example below
Atomic inventory reservation with Redis (prevents oversells):
// lib/inventory.js
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
// Initialize inventory in Redis before the sale
export async function initializeInventory(productId, quantity) {
await redis.set(`inventory:${productId}`, quantity);
}
// Atomic check-and-decrement using Lua script (runs on Redis server, no race conditions)
const LUA_RESERVE = `
local current = tonumber(redis.call('GET', KEYS[1]))
if current == nil then return -1 end
if current < tonumber(ARGV[1]) then return 0 end
redis.call('DECRBY', KEYS[1], tonumber(ARGV[1]))
return 1
`;
export async function reserveInventory(productId, quantity) {
const result = await redis.eval(LUA_RESERVE, 1, `inventory:${productId}`, quantity);
if (result === 1) return 'reserved';
if (result === 0) return 'out_of_stock';
return 'not_found';
}
export async function releaseInventory(productId, quantity) {
await redis.incrby(`inventory:${productId}`, quantity);
}
Queue-based order intake (fast response, async processing):
// checkout API — responds instantly, processes in background
export async function POST(req) {
const order = await req.json();
// 1. Reserve inventory atomically
const reservation = await reserveInventory(order.productId, order.quantity);
if (reservation === 'out_of_stock') {
return Response.json({ error: 'Sold out' }, { status: 409 });
}
// 2. Enqueue — responds to user in <100ms
const orderId = crypto.randomUUID();
await sqs.send(new SendMessageCommand({
QueueUrl: process.env.ORDER_QUEUE_URL,
MessageBody: JSON.stringify({ orderId, ...order }),
}));
return Response.json({
orderId,
status: 'queued',
message: 'Your order is being processed. You will receive a confirmation email shortly.',
});
}
// Background order processor (separate service consuming SQS)
export async function processOrder(message) {
const order = JSON.parse(message.Body);
try {
await capturePayment(order);
await db.orders.create(order);
await sendOrderConfirmationEmail(order);
} catch (err) {
await releaseInventory(order.productId, order.quantity); // release on failure
throw err; // let SQS retry
}
}
Circuit breaker for payment processor:
import CircuitBreaker from 'opossum';
const paymentBreaker = new CircuitBreaker(captureStripePayment, {
timeout: 5000, // 5s timeout per call
errorThresholdPercentage: 30, // open if 30% fail
resetTimeout: 30000, // try again after 30s
});
// Fallback: queue for retry instead of failing the customer
paymentBreaker.fallback(async (order) => {
await sqs.send(new SendMessageCommand({
QueueUrl: process.env.PAYMENT_RETRY_QUEUE_URL,
MessageBody: JSON.stringify(order),
DelaySeconds: 30,
}));
return { status: 'payment_queued' };
});
Kubernetes pre-scale CronJob:
apiVersion: batch/v1
kind: CronJob
metadata:
name: flash-sale-prescale
spec:
schedule: "30 11 * * 5" # 30 min before noon Friday sale
jobTemplate:
spec:
template:
spec:
containers:
- name: scaler
image: bitnami/kubectl
command: [kubectl, scale, deployment/checkout-service, --replicas=100]
restartPolicy: OnFailure
Redis waiting room for extremely high-demand drops:
// Fair queue: customers get a position number when they arrive
export async function enterWaitingRoom(sessionId, productId) {
const queueKey = `sale_queue:${productId}`;
await redis.zadd(queueKey, Date.now(), sessionId); // sorted set, score = timestamp (FIFO)
const position = await redis.zrank(queueKey, sessionId);
return { position: (position ?? 0) + 1 };
}
// Periodically admit batches to checkout
export async function admitFromQueue(productId, batchSize) {
const admitted = await redis.zpopmin(`sale_queue:${productId}`, batchSize);
// Notify each admitted customer they can proceed to checkout
for (let i = 0; i < admitted.length; i += 2) {
await notifyCustomerAdmitted(admitted[i], productId);
}
}
| Problem | Solution |
|---------|----------|
| Oversells despite inventory check | Use Redis atomic Lua script for check-and-decrement; never check inventory in the application layer then update separately in two operations |
| Auto-scaling too slow to respond | Pre-warm to minimum capacity 30 minutes before the event; configure scale-out cooldown to 30 seconds, not the default 5 minutes |
| Circuit breaker opens on brief latency spike | Tune volumeThreshold and errorThresholdPercentage conservatively; use timeout as the primary trigger rather than error rate for flash sales |
| WooCommerce oversells during a spike | Enable WooCommerce stock management and set Hold stock to 60 minutes; upgrade to a host with Redis Object Cache to reduce database lock contention |
tools
Let shoppers save products to a wishlist, share it with friends, and get notified when saved items come back in stock or drop in price
development
Build a themeable storefront with design tokens and CSS custom properties that supports white-labeling, multi-brand variants, and dark mode
development
Speed up product discovery with instant search suggestions, fuzzy typo matching, and category-aware results powered by Algolia or Elasticsearch
development
Build a mobile-first storefront with thumb-friendly navigation, sticky add-to-cart buttons, and touch-optimized components for high mobile conversion