Why Online Stores Crash During Mexico's Buen Fin (and How to Prevent It): The 2026 Technical Guide

A queue of miniature shopping carts piles up in front of a funnel next to a laptop showing an online store, and a server whose gauge needle is in the red
Table of Contents

    El Buen Fin, Mexico’s answer to Black Friday, runs from Friday November 13 to Tuesday November 17, 2026. Almost everything published about getting a store ready for it is about banners, coupons and email. This guide is the other half: what breaks technically when the visitors you paid to attract all show up at once, and what to do beforehand. Nearly all of it is written down in your host’s, your payment gateway’s and your platform’s documentation, and almost nobody reads it until the store is already down.

    Last year’s numbers show why it matters. According to Mexico’s Ministry of Economy, the 2025 edition sold 219.2 billion pesos, and digital commerce was 21% of the total, growing 31% year over year. The public AMVO report (Mexico’s online sales association) counted 1.686 billion page views on e-commerce sites and traffic 56% higher than the previous edition (which went from four days to five). The retailers’ association ANTAD reports that the last day alone took 26.1% of online sales. The peak doesn’t spread out: it arrives, and it arrives all at once.

    If you sell into Mexico from abroad, or build stores for Mexican clients, the local details are what catch people out: the cash-at-OXXO payment method, the Mexican shared-hosting plans small businesses actually run on, and a gateway landscape where Mercado Pago matters as much as Stripe. I’ve built WooCommerce stores with catalogues in the thousands, Mercado Pago payments and WhatsApp checkout. This is what I check on each one before a date like this, with a source for every limit.

    What those five days look like

    Buen Fin 2025FigureSource
    Total sales219.2 billion pesosMinistry of Economy
    Online sales21% of the total, +31% YoY (45.9 billion per AMVO)Economy / AMVO
    Traffic to online stores+56% over the 5 days, +24% on comparable daysAMVO (Similarweb data)
    Average ticket$1,063 MXN online vs $780 overallMexican Banking Association, cited by Economy
    How people paid onlineCredit 48%, debit 43%, store cards 17%, card-free instalments 12%, cash at retail chains 12%AMVO
    Consumer agency complaints220 filed, 205 settled; mostly unhonoured prices and refused deliveryProfeco

    Two rows matter for the technical side. One in eight online buyers paid cash at a retail chain (OXXO and similar), which has a consequence for your inventory that I explain below. And 37% of consumers, per the AIMX survey the ministry cites, fear a data leak: an expired-certificate warning or a checkout page that looks off on your busiest day costs sales even if the site stays up.

    Not everything that fails is yours, either. During Buen Fin 2024, Santander and BBVA customers reported card payment failures; during Hot Sale in May 2026 BBVA confirmed on X that its systems were down, with over five hours of Downdetector reports. And on November 18, 2025, the day after Buen Fin ended, Cloudflare had a global outage of more than three hours. You can’t stop your customer’s bank from going down. You can have a second payment method ready when it does.

    1. Shared hosting has a ceiling, and it’s in writing

    The shared hosting plan that costs a few hundred pesos a year isn’t “slow”: it has exact limits, and when you hit them it doesn’t slow down, it returns errors. Hostinger publishes its limits on its plan parameters page and says reaching them produces “503 – Service temporarily unavailable”:

    Hostinger planCPURAMConcurrent PHP workersMySQL connections
    Web Single11 GB2025
    Web Premium12 GB4050
    Unlimited (formerly Business)23 GB6075

    HostGator Mexico puts it differently in its help centre: a cap of 25% CPU sustained for 90 seconds or more, and 25 concurrent processes per cPanel account.

    Do the maths with your own store. An uncached WooCommerce product page holds a PHP worker while it renders. If it takes one second and you have 20 workers, your ceiling is about 20 pages per second; visitor number 21 doesn’t wait in line, they get an error. That’s why caching, next, isn’t an optimization: it decides whether those limits ever reach you.

    2. Caching: what can be cached and what can’t

    The idea is simple: most visitors, the ones just browsing, should get a prebuilt copy of the page and cost your server nothing. Only the cart, checkout and account pages need to reach the server every time.

    What almost nobody knows is that Cloudflare doesn’t cache HTML by default, on free or paid plans. Its documentation is explicit: “The Cloudflare CDN does not cache HTML or JSON by default.” If you put your store behind Cloudflare and configured nothing else, images, CSS and JavaScript are cached, but every page still hits your host. The free plan gives you up to 10 Cache Rules and one is enough. This expression is for a Spanish-language WooCommerce store (adjust the paths to yours):

    (http.host eq "tutienda.mx"
     and not starts_with(http.request.uri.path, "/wp-admin")
     and not http.request.uri.path contains "/carrito"
     and not http.request.uri.path contains "/finalizar-compra"
     and not http.request.uri.path contains "/mi-cuenta"
     and not http.cookie contains "woocommerce_items_in_cart"
     and not http.cookie contains "wordpress_logged_in")
    

    With the “Eligible for cache” action and a short edge TTL (5 to 10 minutes), browsers get the cached copy, and anyone with something in the cart or a logged-in session goes straight to your server. Two warnings:

    • Purge the cache when prices change. If your discounts start at midnight on the 13th, a copy cached at 11:58 pm still shows the old price, and “the price wasn’t the advertised one” is among the complaints Profeco receives most. Purge when you switch the offers on.
    • A cookie on every page breaks everything. Cloudflare won’t cache a response carrying Set-Cookie, and some plugins (currency switchers, geolocation, popups) send one on every visit. Check it like this:
    curl -sI https://tutienda.mx/producto/tu-mas-vendido/ | grep -iE "set-cookie|cf-cache-status"
    

    What you want to see, from the second request on, is cf-cache-status: HIT and no set-cookie. If you see DYNAMIC or BYPASS, that page is still hitting your server.

    Two things look like safety nets and aren’t. Always Online is on every plan, but it only kicks in on 52x errors, serves Internet Archive snapshots and can’t serve dynamic content: nobody checks out from an archived copy. And Cloudflare’s Waiting Room, the virtual queue big retailers use, only exists on Business and Enterprise plans.

    On WooCommerce, also check cart fragments: the script that updates the cart counter by calling the server on every page. WooCommerce acknowledges that on heavily trafficked stores “this could severely impact the load on the server”, and since version 7.8 it no longer loads on every page, but plenty of themes and plugins turn it back on. Open a product page with your browser’s dev tools and look for a request to ?wc-ajax=get_refreshed_fragments. If it fires on pages without a mini cart, that’s one server request per visit that caching can’t remove.

    And slim down your product photos: they’re most of a store’s page weight, and on mobile, where most Mexican shoppers buy, every megabyte shows.

    3. Your payment gateway has a limit too

    The server isn’t the only thing that can say no. Stripe publishes its rate limits: 100 requests per second in live mode, with most individual endpoints capped at 25. And it says plainly that “a sudden increase in charge volume, such as a flash sale, might result in rate limiting”; if you expect a spike, it asks you to contact support beforehand. Mercado Pago doesn’t publish a number, but its Orders API answers 429 Too Many Requests with a Retry-After header when you exceed it.

    For a small business, 100 charges a second is plenty. The problem shows up when the integration makes several calls per purchase (create customer, create payment intent, poll status) or retries without backing off: a badly handled 429 becomes “we couldn’t process your payment” for a customer who had the funds.

    Bank verification (3-D Secure, the “confirm in your app” screen) changes the flow too. Mexico has no regulatory mandate for it, but Mercado Pago recommends enabling it in optional mode, and when the bank asks for a challenge the payment sits in pending with detail pending_challenge. If your integration treats “pending” as “declined”, you’re cancelling good orders. AMVO lists “payment method rejected” among the barriers to buying online.

    4. The problem nobody mentions: cash at OXXO locks your inventory

    This is what worries me most for a store with limited stock, and I didn’t see it in any Buen Fin guide I read. When a customer chooses to pay cash, the gateway issues a voucher with an expiry date, and until they pay, the item is in limbo:

    GatewayVoucher validityIf they pay late
    Stripe (OXXO)5 days by default, configurable from 1 to 7; confirmation arrives the next business dayThe voucher expires (docs)
    Mercado Pago (OXXO, Paycash)Configurable from 1 to 30 days; they recommend 3. Crediting takes up to 2 business hours“The amount will be refunded” (docs)
    ConektaSet by your integration with expires_at; signalled by the order.expired webhookUp to your integration (docs)

    Now the WooCommerce side. Its “Hold stock” setting reserves items for orders pending payment for as long as you configure (60 minutes is the recommended value) and then cancels them, according to its guide. But the same guide says delayed payment methods leave the order on hold, where that automatic cancellation doesn’t apply. If your gateway plugin doesn’t cancel the order when the voucher expires, the item stays reserved for days by someone who may never pay, while you tell the customer holding a card that it’s sold out.

    Before the 13th:

    1. Shorten voucher validity for the campaign. One or two days instead of five or thirty.
    2. Check that your plugin cancels the order on expiry. Place a test cash order with the minimum validity, don’t pay it, and check the next day that the order was cancelled and the stock came back.
    3. If you sell over WhatsApp with payment links, give them a short expiry. Clip, for example, lets a link expire the same day.

    5. Overselling: two people buy the last unit

    Since version 4.3, WooCommerce reserves stock during checkout to stop two simultaneous purchases taking the same unit (PR #26395). Even so, issue #44273, where the team confirms that “a race condition like this is possible”, is still open today. On a normal day it almost never happens. During Buen Fin, with hundreds of people on your best seller, is when it does.

    For low-stock products: keep a buffer (list 18 if you have 20), cap quantity per customer, and decide in advance what you’ll do if it happens, with an apology and a fast refund. Refused delivery was among the complaints that dominated Profeco’s 2025 figures. Shopify’s flash sale guide recommends switching to manual payment capture for the same reason: charge only for what you can actually ship.

    6. What runs in the background

    Order confirmation emails, payment webhooks and stock updates in WooCommerce go through Action Scheduler, which by default processes batches of 25 actions for 30 seconds, triggered by WP-Cron. And WP-Cron only runs when someone visits the site. With caching done right, hardly anyone reaches the server, and tasks can pile up. The result: customers who paid and don’t get their confirmation, and message you asking whether the order went through.

    The fix is a real server cron instead of the visit-driven one: set DISABLE_WP_CRON in wp-config.php and schedule a call to wp-cron.php every minute from your hosting panel. Almost every shared host allows it.

    7. Test it first with fake traffic

    All of the above can be checked without waiting for the 13th. A load test simulates many visitors at once and shows you where errors start. Two free options:

    A minimal k6 script that visits the home page and your best seller:

    import http from 'k6/http';
    import { check, sleep } from 'k6';
    
    export const options = {
      stages: [
        { duration: '2m', target: 50 }, // ramp to 50 concurrent visitors
        { duration: '5m', target: 50 }, // hold
        { duration: '1m', target: 0 },
      ],
      thresholds: {
        http_req_failed: ['rate<0.01'],     // under 1% errors
        http_req_duration: ['p(95)<2000'],  // 95% under 2 seconds
      },
    };
    
    export default function () {
      check(http.get('https://tutienda.mx/'), { home: (r) => r.status === 200 });
      sleep(3);
      check(http.get('https://tutienda.mx/producto/tu-mas-vendido/'), { product: (r) => r.status === 200 });
      sleep(5);
    }
    

    Run it with k6 run test.js. Three rules: test pages, never your payment gateway; on shared hosting, tell your provider first, because a load test looks a lot like an attack; and aim at three to five times your normal peak hour. There’s no public figure for how much a small store’s traffic rises during Buen Fin compared with an ordinary day; if your analytics kept last year’s, use that. If the test fails at 50 visitors, you know what to fix, and you have seven weeks to do it.

    If your store runs on Shopify or Tiendanube

    Infrastructure isn’t your problem: Shopify handled 489 million requests per minute at its edge over Black Friday and Cyber Monday 2025, and its guide says special preparation is only needed if you expect “tens of thousands of customers” starting checkout within minutes. Yours are the other sections: theme weight and the apps you load on every page, the gateway and its pending states, cash voucher validity, and your stock buffer.

    The two-weeks-before checklist

    WhatHow you verify it
    HTML caching on for browserscf-cache-status: HIT on the second request to a product page
    No page sends Set-Cookie to visitorsThe same curl -sI as above
    Cart, checkout and account excluded from cacheAdd something to the cart in another window and check the counter updates
    New prices visiblePurge the cache when offers go live and check in a private window
    Short cash-voucher validityTest OXXO order you don’t pay: on expiry, order cancelled and stock back
    “Pending” payments treated as pendingTest purchase with 3-D Secure that you don’t complete
    Real server cronDISABLE_WP_CRON in wp-config.php and a task every minute
    Buffer on best sellersListed stock below real stock
    SSL certificate valid past November 17SSL lookup
    Load test passedk6 or Loader.io with no errors at three times your peak
    Plan B for paymentsPayment link and WhatsApp ready in case the gateway or the bank fails

    If you need a store or site in Mexico built to survive a date like this, that’s what I do.

    Frequently asked questions

    When is Buen Fin 2026?

    From Friday November 13 to Tuesday November 17, 2026. It is the 16th edition and runs five days because it includes Monday November 16, the observed Revolution Day holiday. Business registration is free at elbuenfin.org, from September 8 to November 12.

    Why do online stores crash during Buen Fin?

    Usually because every visit reaches the server uncached and the host runs out of the processes it allows. Shared plans have fixed limits (20 PHP workers on Hostinger's entry plan, 25 processes per cPanel account on HostGator Mexico) and return a 503 error past them. The payment gateway can also fail when it rate-limits, or the customer's bank, which is out of your hands.

    Does Cloudflare's free plan protect a store from Buen Fin traffic?

    It helps, but not just by switching it on. Cloudflare does not cache HTML by default, so without a Cache Rule every page still hits your host. The free plan allows up to 10 rules, and one is enough to cache pages for browsers while excluding cart, checkout and account. The virtual queue (Waiting Room) only exists on Business and Enterprise plans.

    Does a pending OXXO payment lock my inventory?

    It can, for days. Stripe OXXO vouchers expire after 5 days by default (configurable from 1 to 7) and Mercado Pago's after 1 to 30. In WooCommerce, delayed-payment orders go on hold and the 60-minute hold-stock setting only cancels orders pending payment, so the item stays reserved until the gateway plugin cancels the order when the voucher expires. Shorten validity for the campaign and test it with an order you do not pay.

    How do I load test an online store?

    With k6, free and open source, or Loader.io, whose free plan runs up to 10,000 clients in a one-minute test. Simulate visitors on the home page and best sellers, never on the payment gateway, aim at three to five times your peak hour, and warn your shared hosting provider first, because a load test looks like an attack.

    Found it useful? Share it

    Found it useful? Get the next one by email

    Once a week: what breaks when you upgrade, AI for developers and what I'm building, with sources. No spam.

    By subscribing you accept our privacy policy.

    Search

    Tags

    Migration AI PHP Laravel JavaScript Tutorial Web Development Upgrade Best Practices Security OpenAI SEO Backend Claude Laravel 13