Shopify showed paying merchants a "This store does not exist" page. The monitoring lesson is brutal.
On the morning of June 3, Shopify went down for about two hours. Admin, checkout, storefronts, and Retail POS all took hits at once, and DownDetector logged more than three thousand reports before the spike settled. Shopify flagged the problem on its status page at 9:27 a.m. EDT and called it resolved by 11:31. As outages go, two hours is survivable. That is not the part worth your time.
The part worth your time is what customers saw. During the outage, visitors who tried to load some merchant storefronts got a page that said "This store does not exist." And on that page, according to merchants posting screenshots, sat an advertisement to start a free Shopify trial. So for a stretch of a Wednesday morning, brands paying Shopify to host their storefront had that storefront replaced with a message telling their customers the store was never real, next to a pitch recruiting those same customers to build a competing one.
One merchant put it cleanly in a reply to Shopify support: change the "This store does not exist" page to one that says "We are experiencing an outage, we will be back soon." Having paid stores resolve to a does-not-exist page, they said, is insane. They are right, and the reason this happened is the reason I want to walk through it.
What broke, and what Shopify still has not said
Here is the honest state of the record: as of this writing, Shopify has not published a root-cause postmortem for the June 3 incident. We know the symptoms and the timeline. We do not know the mechanism, and I am not going to invent one. What we can read with confidence is the shape of the failure from the outside, because the symptoms tell you a lot.
A storefront resolving to "This store does not exist" is not the signature of a server that fell over. A dead server gives you a timeout, a 502, or a blank connection error. A specific, branded "does not exist" page is something the platform chose to serve. That page is the fallback Shopify shows when its routing layer cannot map a hostname to a live store, the same page a genuinely deleted store would show. During the outage, the lookup that turns a customer's domain into "here is your store" was failing or returning empty, and the system did what it was told to do with an unknown store: serve the does-not-exist page, ad and all.
That is a routing or store-resolution failure wearing the costume of a deleted account. The infrastructure underneath was almost certainly fine. The store data existed. The servers answered. The layer that connects a request to the right store is what blinked, and the default it fell back to was the worst possible message to show a paying customer's shoppers.
The error page was a product decision, made on a calm day, that detonated on a bad one
Somebody, at some point, decided that an unresolvable storefront should show "This store does not exist" with a Shopify signup pitch. On a normal day that is correct. If you type a domain for a store that was closed or never existed, that is exactly the right page. The decision was reasonable in the context it was made in.
The trap is that the same page serves two completely different situations that look identical to the routing layer: a store that truly does not exist, and a live store the system temporarily cannot find. The first deserves the recruiting ad. The second deserves a soft "we will be right back." The system could not tell them apart, so it treated a platform-wide outage as three thousand individual deleted stores and advertised over the top of all of them.
This is a pattern worth naming because it shows up everywhere, not only at Shopify scale. Your fallback behavior is written on a calm day for the common case, and then a rare failure routes a huge volume of legitimate traffic straight into the path you designed for the rare exception. The default that was harmless becomes the headline. If you have a catch-all error page, a default route, or a "user not found" screen, ask what happens when a real outage shoves ten thousand valid requests through it at once.
Your internal health checks would have stayed green
Now put yourself on a merchant's side of this. Suppose you run a Shopify store and you have monitoring on it. What does that monitoring really watch? For most stores the answer is: nothing they control. Shopify hosts the storefront, so the merchant has no server to ping, no process to health-check, no dashboard that would have gone red. The first signal they got that their store was serving a does-not-exist page was a customer telling them, or a screenshot on social media.
And here is the deeper cut, the one that applies even if you do run your own infrastructure: an internal health check would have passed this whole time. Shopify's own servers were up. A liveness probe hitting the application would have come back 200. The database was there. By every internal signal, the platform was healthy. The thing that was broken, store resolution returning the wrong page, is invisible to a check that asks "is the process running" instead of "does the customer see the right thing."
That gap is the entire lesson. A health check that lives inside your system, and tests your system the way your system thinks about itself, will tell you everything is fine right up until your customers are looking at a competitor's ad on your homepage. The check passed. The business failed. Both were true at the same time.
The only check that catches this runs from outside, and looks at what the customer looks at
The monitoring that would have caught the June 3 failure is the kind that does not trust the system to report on itself. It hits the real public URL of your store from somewhere external, on a schedule, loads what an actual visitor loads, and checks for something only a working store has: your product name in the title, a price on the page, the word "checkout," anything that proves a real store rendered rather than a fallback. The moment that string disappears and "This store does not exist" appears, it screams.
This is unglamorous and it is exactly the layer almost nobody owns. Internal monitoring is built by the team that built the system, so it inherits the system's blind spots. It watches CPU and error rates and queue depth, the things the team already worries about. It does not watch the one thing the customer cares about, which is whether the front door opens and shows the right room. An outside check has no blind spots inherited from your architecture, because it does not know or care about your architecture. It knows what a customer sees.
I build a small product in exactly this space, so I will be upfront that I have skin in the argument. The reason I built it is that I kept watching teams discover their own outages from customers instead of from their tooling, and the fix was almost always the same shape: a watcher that runs outside the thing it watches, on a clock, that pages a human the second the public-facing reality stops matching what the dashboards claim. A scheduled job that is supposed to hit your storefront every minute and report when the response stops looking like a real store. A cron check that fails loud when it silently stops getting the answer it expects. That is the layer that turns "a customer told us" into "we knew before the customer did."
A short checklist I would run this week
- Check your real public URL from outside, not your server from inside. Internal liveness probes pass during exactly this failure. Load the actual customer-facing page from a machine that is not yours and assert on content a working page has.
- Assert on a string only success produces. A 200 status is not proof. A does-not-exist page returns 200 too. Check for your product name, a price, the checkout button, something a broken fallback would not contain.
- Audit your own fallback pages. Find every catch-all, default route, and not-found screen. Ask what a real customer sees if a real outage routes legitimate traffic into it, and whether that message protects your brand or undermines it.
- If you host on a platform, you still need the watcher. Being on Shopify, Vercel, or anyone else does not give you monitoring of your store. It gives them monitoring of their platform. The gap between those two is where June 3 lived.
- Page a human in under a minute. If your fastest path to learning the storefront is broken is a customer's screenshot, your alerting system is your customers, and they did not sign up for the job.
Shopify will be fine. Two hours of downtime is recoverable and they have weathered worse. The merchants are the ones who absorbed the real cost, because for a morning their stores told shoppers they did not exist and pointed them at a signup form, and most of those merchants found out too late and too publicly. The platform's blind spot became their problem. The way you keep it from becoming yours is to stop asking your own system whether it is healthy and start asking the internet what your customers can see.