In most store engines, a product's price is a single number in a single database field. It works flawlessly as long as the store has one warehouse and sells to everyone at the same price. The problem starts the moment a second warehouse with its own purchase cost appears, or a wholesale buyer who needs a different price for the same product.
This article is about why "one product — one price" breaks exactly at that point, and what we had to work out inside the core of our own LiteShop engine to avoid it.
Where the single-price model actually breaks
Imagine a store with two warehouses: one in Kyiv, where the product arrived at an old purchase price, and one in Lviv, the same item but brought in later and more expensive. A classic engine, where price is tied to the product rather than to the pair "product + warehouse," forces a choice: either keep two separate product records for the same item (confusing the customer with a choice between two "identical" products), or sell from one warehouse at a loss until the average purchase price evens out.
The same problem applies to wholesale tiers: a regular client whose orders exceed a certain threshold should get a different price for the same SKU than a retail buyer. If price is a single field, this requires either a manual discount system layered on top of the standard engine, or a separate price list that is synced by hand and drifts from the main catalogue within the first week.
What this means for the architecture, not just the interface
The right solution is not cosmetic (adding a "discount" field to the product card) but structural: price has to belong to the pair "product + warehouse" and be further modified by the buyer's level. That means a separate pricing table rather than one field, and logic that picks the correct price row on every product-page view and every cart calculation — without slowing the page down, because this calculation runs on every request.
We built this logic into the core of our own LiteShop engine: multiple warehouses with different purchase prices for the same product, wholesale price tiers, and warehouse accounting — not a layer bolted onto a standard engine, but part of how the product model is built from the start. 42 core modules (delivery, payment, warehouse, loyalty, SEO) are switched on in the admin panel rather than installed as separate plugins that later conflict with one another.
Does this slow the store down
Extra price-calculation logic on every view is a natural question about speed. On the production instance of one store built on this engine (Hetzner cx43), the homepage's first response is the same cold as warm — 167 ms, measured on 19 May 2026. This is possible precisely because the price calculation by warehouse and client level is cached in Redis: measurements on 12 June 2026 showed a 98.3% cache hit rate with zero evicted keys — the cache does not fill up and drop current data even under live load.
What the engine does not do yet — honestly
There is no timed reservation of stock in the cart: inventory is deducted when the order is placed, not when it's added to the cart. There is no direct catalogue import from OpenCart. Integrations with Rozetka Delivery and Meest are currently stubs, not a working feature. These limits are not hidden in fine print but stated directly: the engine is young, and multiple warehouses with wholesale tiers are the part built solid from day one, with the rest added on sequentially.
Who actually needs this
If you have one warehouse, a few hundred products, and no plans for wholesale tiers or custom work, a standard engine or a rented builder will be cheaper, and an honest assessment will say so in the first email, not after payment. The need for a structural solution shows up with a second warehouse or supplier, the need for wholesale price tiers, or when a standard builder already runs into its own limits.




