Practical WordPress guide

Vacation Mode for WooCommerce: safe setup, failure cases, and rollback

A plain-language guide for nontechnical site owners. It separates what the parent plugin really knows from what a helper plugin should never guess.

Reviewed July 21, 2026Official-source links includedNo invented performance claims

Direct answer

Change purchasability, not the catalog. While one switch is on, every product answers not purchasable through WooCommerce's native purchasability filters, new add-to-cart and checkout submissions are rejected server-side with one notice, and one short store notice explains the break. Products, prices, stock, existing orders, and browsing stay exactly as they were. Turning the switch off restores native behavior immediately, and because nothing was written, there is nothing to restore. Do not set products out of stock and do not hide the shop behind a maintenance page.

Vacation Mode for WooCommerce follows that read-time boundary. Free adds one switch and one 160-character notice. Pro adds a return date that reopens the store lazily at read time, up to twenty-five category exceptions that stay purchasable, and a second notice position.

Pausing orders is not hiding the store

A store owner who takes a break wants two things at once: no new orders, and a catalog that keeps working for browsing, search, and ads. The common workarounds trade one for the other:

Approach What it changes Main failure surface
One purchasability switch The purchasable answer at read time Forgetting to switch back, which a return date covers
Manual out-of-stock edits Every product's stock state, then a manual revert Revert drift and wrong stock counts afterward
Maintenance page The whole storefront Browsing, search visibility, and ad landing pages blocked
Scheduler suite Calendars, cron events, opening hours Missed events, timezone bugs, background-job upkeep

Public support reports show the same request. One merchant asked how to temporarily stop users from placing orders while the website stays open for browsing. A food store owner asked how to restrict ordering on closed days. A separate topic reports customers still placing orders while the shop was supposed to be closed, which shows why the block must be enforced server-side and not by hiding buttons. These reports document individual incidents only. They do not establish that every store faces the same gaps.

Let WooCommerce own the catalog

Products, prices, stock, and orders belong to WooCommerce. A pause helper should only change the answer to one question — can this be purchased right now — while the switch is on. That rule prevents several dangerous shortcuts:

  • Do not edit stock values, prices, sale dates, or product visibility.
  • Do not touch existing orders, completed carts, or customer records.
  • Do not hide products, redirect shoppers, or replace pages with maintenance screens.
  • Do not run cron, schedulers, weekly calendars, or countdown timers.
  • Do not inject JavaScript or CSS to conceal purchase controls; enforce the block server-side.

WooCommerce's current abstract-wc-product.php source is the authoritative reference for purchasability. The lesson is ownership: WooCommerce owns the product; a narrow plugin can own only the temporary not-purchasable answer.

Decide at read time, reject at submit time

The safe flow has four parts:

  1. Read the owned switch, and in Pro the return date, at decision time.
  2. While on, products and variations answer not purchasable through the native filters.
  3. New classic add-to-cart and checkout submissions are rejected server-side with at most one escaped notice per request.
  4. One sanitized notice renders through WooCommerce's native store notice output.

The notice text is plain text, capped at 160 characters, sanitized on write and escaped on output; WordPress's sanitize_text_field() reference documents the sanitization primitive. A Pro return date is compared lazily when a page is read: once the date passes, the store is open, with no cron event and no write. Items a shopper carted before the break are rejected at checkout with one notice, and the cart itself is left unchanged.

Why server-side rejection matters

A hidden button or a banner is a request, not a rule. A shopper with a stale page, a direct link, or a restored cart can submit past cosmetic blocks. Validation on the server rejects the add-to-cart and checkout submissions themselves, so the pause holds even when the page a visitor sees is out of date. The notice explains; the rejection enforces.

Classic add-to-cart and checkout are the covered submission paths. A block-based checkout surface is a separate boundary this release does not rewrite.

Turn it on and prove the pause

  1. Open WooCommerce > Vacation Mode.
  2. Turn on Vacation Mode and optionally edit the one-line notice.
  3. Save, then preview the shop while signed out.
  4. Confirm products still browse with normal price display but cannot be purchased.
  5. Submit a test checkout and confirm it is rejected with the notice and no order is created.
  6. When the break ends, turn the switch off and confirm purchasing works immediately.

The correct pass condition is a visible catalog with a working block. If products disappear or prices change, the tool is editing the catalog, which is a different and riskier job.

Diagnose a leaky pause

Symptom Check first Safe expected result
A checkout went through Server-side validation on the exact submission path New classic submissions rejected with one notice
Buttons hidden but orders arrive Cosmetic-only blocking Server-side rejection, not hidden controls
Notice missing Whether the theme renders the native store notice One notice where the theme supports native output
Return date passed but store looks closed Pro date value and site timezone Store treated as open at read time
Pre-break cart checked out Checkout validation Rejected with one notice; cart contents unchanged
Category should stay open Pro exception list Excepted category stays purchasable
Switch off but still blocked Page cache serving stale output Native purchasing returns; clear the page cache
Variation stays purchasable Variation filter coverage Variations answer not purchasable too
Notice appears twice Another plugin printing its own store notice One notice per request from this switch

Start with the switch and one signed-out test order. A page cache can serve a stale purchasable page for a few minutes; the server-side checkout rejection is the backstop that still protects the store.

Test the negative space

The most important checks prove what did not change:

  1. Products, prices, stock, and visibility are unchanged before and after.
  2. Existing orders, drafts, and customers are untouched.
  3. Switch off or deactivation restores native purchasing immediately.
  4. A passed Pro return date reopens the store with no scheduled job.
  5. WooCommerce missing causes no fatal error and registers nothing.
  6. Pro or the license API unavailable leaves the Free switch and notice working.
  7. Update, downgrade, rollback, and uninstall preserve every product and order.
  8. A forged or malformed settings value leaves native purchasability untouched.
  9. Notice text is capped at 160 characters, sanitized, and escaped on output.

Release acceptance for this product should run those drills on a real WordPress and WooCommerce installation before any store trusts it with a live catalog.

Keep the notice honest

The storefront notice is one plain-text line, capped at 160 characters, sanitized on write and escaped on output. It states the pause and, in Pro, the return date. Fake urgency, countdown timers, popups, and injected scripts would widen the trust surface without telling the visitor anything new. The Pro return date renders as plain text inside the same notice; it is a fact, not a timer.

Resource boundary

A pause decision needs one autoloaded option read per purchasability check and one notice render. It needs no cron event, custom table, product query, remote request, JavaScript, stylesheet, or idle work. The Pro return date is a comparison at read time, not a scheduled task, so reopening cannot be missed by a failed cron run.

Common mistakes

Marking everything out of stock

Stock edits must be reverted one by one, and a missed product sells with wrong counts afterward. Read-time purchasability leaves stock data alone.

Using a maintenance page

The shop vanishes for browsing visitors, search engines, and paid campaigns. Pause orders; keep the catalog visible.

Trusting a notice or a hidden button

Client-side hiding can be bypassed by a direct submission. Reject add-to-cart and checkout on the server.

Scheduling reopening with cron

A missed or disabled event leaves the store closed. Compare the return date lazily when a page is read.

Forgetting the switch entirely

A store that stays paused after the owner returns loses real orders. Free relies on the owner flipping the switch; Pro's return date exists for exactly this miss.

Market boundary

The official WooCommerce Marketplace lists a current Store Vacation offer at $39 per year, and WordPress.org has established vacation plugins. That proves a paid category exists. It does not prove demand for a write-free switch. StoreFixKit Pro is $39 per year for a single site; measure StoreFixKit installs, completed pauses, paid conversions, refunds, and support load rather than inheriting a competitor's numbers.

FAQ

Can customers still browse while the store is paused?

Yes. Only purchasability changes. Products, prices, images, and pages stay visible, and one notice explains the break.

What happens to orders placed before the break?

Nothing. Existing orders stay native, and you fulfill them normally. The switch affects only new purchase attempts.

Do I have to remember to reopen the store?

With Free, yes; turn the switch off when you return. With Pro, set the return date and the store reopens at read time with no scheduled job.

Focused plugin

Use the one-job implementation.

Pause new orders with one switch while the store stays visible: every product reports not purchasable through native filters, new add-to-cart and checkout submissions are rejected server-side, and one sanitized notice renders.