Turning the store off without losing it

What the extension toggle really does, why a lapsed licence 403s instead of 404ing, what customers lose, and the safer way to close the store for a maintenance window.

9 min readUpdated 6 August 2026extension, disable, maintenance, licence, downtime

Install and enable covers switching the store on. The reverse comes up for maintenance, for a migration, and — uninvited — when a licence lapses. It is worth knowing before you need it, because the obvious move is not the one that does what you want.

Turning E-commerce off at System → Extension Manager removes the store from the navigation. It does not close the API, does not stop a checkout, and does not pause anything. Meanwhile the thing that does 403 every request — an invalid licence — is not something you choose.

Neither one deletes a row. If your goal is "stop taking orders for two hours", deactivate your products instead.

Two switches, and only one of them refuses requests

The extension toggle The licence
Where it lives status on the extension row where name = 'ecommerce' lic/44624493.lic on the server's disk
Set from System → Extension Manager (/admin/system/extension) The activation screen, /admin/system/license
Controls Menus, and everything that reads "is this addon in use" The licence gate in front of every store route
When it is off The store disappears from the nav and keeps working Every store request answers 403

They are independent, and they fail in opposite directions. A toggle that is on with no licence serves a menu that 403s. A licence that is valid with the toggle off serves an API nobody can find a link to.

What the toggle writes

The switch calls PUT /api/admin/system/extension/44624493/status with {"status": false}, on the permission edit.extension. (The bulk form is POST /api/admin/system/extension/status with ids and status.) Two things happen:

  1. One column changes. UPDATE extension SET status = 0 WHERE productId = '44624493'. Nothing else in the database is touched.

  2. The platform cache is cleared, and the clear is broadcast to every worker process, so no restart is needed for the change to be seen. The enabled- extension set is rebuilt from SELECT * FROM extension WHERE status = true, and ecommerce is no longer in it.

From there, the effects are all about who mentions the store:

  • GET /api/settings publishes the enabled-extension names, so the platform's user navigation drops the Store entry pointing at /ecommerce.
  • The admin menu entry for E-commerce is rendered disabled rather than hidden — greyed out, still visible, so you can see it exists.
  • Anything else that asks "is this addon in use" — the admin dashboard, the operations summary, the system health check — stops counting the store.

What the toggle does not do

This is the part that surprises people:

  • The backend routes stay registered. They are read from the filesystem at boot, and nothing re-checks them against the enabled set. /api/ecommerce/* and /api/admin/ecommerce/* keep answering exactly as before.
  • Restarting does not change that. Boot-time route loading is why enabling a freshly installed extension needs a restart; it is also why disabling one cannot take the routes away, restart or no restart.
  • /ecommerce is still reachable by anyone who has the URL, has it bookmarked, or follows a link from an old order email. The storefront renders and its data loads.
  • Checkout still completes. Nothing in the cart or order handlers consults the extension's status.

So a disabled extension is a store you have stopped advertising, not a store you have closed.

The licence gate is the thing that 403s

Every request whose path starts /api/ecommerce or /api/admin/ecommerce is matched to the ecommerce extension by the licence gate, which runs early in the middleware chain — ahead of authentication and rate limiting. It checks that lic/44624493.lic is readable, and caches that answer for five minutes.

When the file is missing or unreadable, the answer is HTTP 403, not 404 and not 503:

{
  "message": "This feature requires a valid license for ecommerce. Please activate your license to continue.",
  "statusCode": 403,
  "licenseRequired": true,
  "productId": "44624493",
  "productType": "extension",
  "productName": "ecommerce"
}

Internally the platform labels this condition Extension license required, which is what you will see referred to elsewhere. Two consequences worth holding on to:

  • 403 reads like a permissions fault. An operator whose licence lapsed overnight spends the morning in CRM → Roles checking store permissions that were never wrong. Check lic/ first — the licenseRequired flag in the body is the tell.
  • Admin and customer surfaces behave differently. In the admin panel the frontend recognises that body and hard-redirects to /admin/system/license?productId=44624493. On the customer side there is no redirect: /ecommerce draws its shell and every panel on it fails.

If the licence check itself throws — a filesystem blip, a database hiccup — the gate for E-commerce falls through and serves the request. Only the two newest paid addons fail closed. So an intermittent 403 across the whole store is a missing or unreadable file, not a flaky check.

Licensing itself — what a .lic is, why it does not survive a server move, and the activation routes — is core's subject: Licences, activation and the extension manager.

What customers lose the moment the licence goes

Everything under /api/ecommerce is behind the same gate, so all of it stops at once:

  • /ecommerce — the landing page, the catalogue, categories, search.
  • /ecommerce/order — their own order history, including orders they placed and paid for years ago.
  • /api/ecommerce/download/{orderItemId} and the file streamer behind it — downloads and licence keys for digital goods they have already paid for.

That last one is the reason a lapsed licence is a support incident and not just an outage. Nothing is deleted; the key, filePath and instructions are still sitting on the order item (see the data model). They are simply unreachable until the licence is restored, and the customer's read of it is "I paid you and now I cannot get my file."

What nothing here touches

Whichever switch is off:

  • No rows are deleted. Products, categories, orders, order items, discounts, shipments, reviews and wishlists are exactly as they were.
  • Wallets and transactions are core's, not the addon's. Every debit, every platform-revenue credit and every shipping-and-tax pass-through stays on the ledger and stays visible in Finance.
  • Order statuses do not move. Nothing sweeps PENDING to CANCELLED, and no refund is issued as a side effect of disabling anything.
  • Attached digital goods stay attached. Re-enabling makes the same download work again with no re-attachment step.

Pending physical orders simply sit there

There is no cron job in this addon — no timeout, no auto-cancel, no abandoned-order sweep, no reminder. A PENDING order stays PENDING indefinitely, holding its stock, until an operator moves it.

That is good news for a maintenance window (nothing expires while you are down) and bad news if you leave the store off for a month: the queue you come back to is the queue you left, and every buyer in it has been charged.

Work the queue down before a long shutdown. See Orders and fulfilment.

Affiliate rewards

Rewards under the ECOMMERCE_PURCHASE condition are created after a checkout transaction commits. No purchase, no reward — so while the store is unreachable, none are created. Nothing retroactively fills them in when it comes back.

Rewards already earned live in the affiliate addon's own tables. They are not touched, they remain visible to the referrer, and they remain claimable. The conditions themselves stay configured.

A maintenance window that actually stops orders

If the goal is "no new orders for the next two hours, and no customer notices anything worse than an empty shelf", do not use the extension toggle. Deactivate the products instead.

  1. Open the catalogue. Admin → E-commerce → Catalog → Products (/admin/ecommerce/product).

  2. Select everything and set the status to inactive. This is edit.ecommerce.product, and it writes status = false on each row. It is a flag, not a delete — no cascade, nothing to restore.

  3. Confirm the shelf is empty. /ecommerce/product returns nothing (the listing filters on status: true), and a direct product URL answers 404.

  4. Do the work.

  5. Set the products back to active the same way.

What that buys you, and why it is the right lever:

Extension toggle off Products deactivated
New orders Still possible Refused — checkout answers Product is not available: <name>
Storefront Loads, unlinked from the nav Loads, with an empty catalogue
Existing order history Visible Visible
Downloads of goods already bought Work Work — deliberately not blocked for a deactivated product
Admin screens Menu entry greyed out Fully usable
Reversible by One toggle One bulk status change

The download behaviour is not an accident: the download handler explicitly allows a deactivated product, on the grounds that a customer who paid keeps access regardless of whether you still sell the thing.

A useful narrower version: deactivate one category (status = false) to take a product line off sale without touching the rest of the catalogue.

Re-enabling

  1. Confirm the licence. /admin/system/extension should show E-commerce with a verified badge. If it does not, activate it from the card — Envato username and purchase code, product id 44624493. The licence check is cached for five minutes, so give a fresh activation a moment.

  2. Toggle the extension on. That sets status = true and clears the platform cache across every process.

  3. Restart the platform if the extension's files changed while it was off — an update, a redeploy, a restored tree:

    pnpm restart

    Routes and models are read at boot. A toggle alone is enough when only the flag moved.

  4. Prove both halves answer. Load /admin/ecommerce as an admin — you want the store dashboard, not a licence redirect — then /ecommerce as a signed-out visitor. The Store entry should be back in the platform nav.

  5. Reactivate anything you deactivated, products and categories both, and check one product page on the storefront.

  6. Walk the order queue. Anything that went PENDING before the window is still PENDING and still waiting.

Two traps

The switch on each card at /admin/system/extension is disabled unless the licence verifies. So an extension that is switched on and has lost its licence cannot be switched off from that screen — the control will not move, and there is no separate error explaining why.

The page names this state directly: a banner lists every product that is switched on without a verified licence, and each entry links to its own activation screen. The way out is to restore lic/ or re-enter the purchase code, not to fight the switch. Fix the licence first; then the toggle works again.

Extension updates extract over the existing tree and never delete files that were removed upstream. After re-enabling following an update, a build or boot error naming a file that is not in the release is almost always a leftover from an older version rather than a bad download — delete the orphan rather than re-running the update.

When it will not come back

Symptom Look at
/admin/ecommerce redirects to the licence page lic/44624493.lic — missing, unreadable, or written on different hardware
Store menu entry still absent after toggling on The settings/extension cache; reload the admin panel, and confirm the row really is status = 1
/admin/ecommerce 404s rather than 403s The extension's files are not on this server. That is an install problem, not a licence one — see Install and enable
Storefront loads but every panel is empty The API is 403ing. Check the browser network tab for licenseRequired: true
Products invisible after re-enabling They are still status = false from your maintenance window

Broader failures are on Troubleshooting.