Shopware 6 Hidden Gems #7: shopware.dal.max_rule_prices — the silent price sorting cutoff
Fabian Blechschmidt
This one is less „cool trick“ and more „you want to know this before it bites you“.
Imagine a grown B2B shop: customer groups, country-specific prices, campaign rules, partner conditions. Over the years the Rule Builder collects rules like my desk collects mate bottles. And one day a customer calls: „I sorted by price, but the cheapest product isn’t first.“ You check the product — the price is right on the detail page. The sorting is wrong. Only for some customers. Good luck reproducing that.
There’s a decent chance you’ve hit an undocumented limit: shopware.dal.max_rule_prices. Default: 100.
What it actually limits
Shopware pre-calculates a „cheapest price“ per product and stores it as a JSON blob (the cheapest_price_accessor column), keyed by rule. When a storefront request filters or sorts by price, CheapestPriceAccessorBuilder builds the SQL that digs into this JSON — one JSON_EXTRACT per rule that is active in the current context, chained so the first matching rule price wins.
And right there sits the cutoff (Content/Product/DataAbstractionLayer/CheapestPrice/CheapestPriceAccessorBuilder.php:32-38):
$keys = $context->getRuleIds();
if (\count($keys) > $this->maxRulePrices) {
$this->logger->warning(sprintf(
'More than %d rules are active, only the first %d rules are considered
for the cheapest price calculation', ...));
$keys = \array_slice($keys, 0, $this->maxRulePrices);
}
$keys[] = 'default';
If the current context — this customer, this sales channel, this cart state — matches more than 100 rules, only the first 100 are considered for price sorting and filtering. The rest fall back to the default price. No exception, no admin warning. Just a warning in the log that nobody reads, and subtly wrong sort orders for exactly the customers who match the most rules. Which, in a B2B shop, tends to be your best customers.
Note the scope: this is the accessor used for filtering and sorting in listings and DAL queries. The price on the product itself is calculated normally — which is what makes the symptom so confusing: correct prices, incorrectly ordered.
Am I affected?
Two quick checks. First, the log — the core literally tells you, in a message I have never seen anyone act on:
grep "rules are active" var/log/prod*.log
Second, count what a heavy context can reach. It’s not the total number of rules that matters, but how many match simultaneously for one customer. If your total rule count is comfortably under 100 you’re safe; if you have several hundred, some customer segment is probably over the line.
The fix (and the trade-off)
The obvious one:
# config/packages/shopware.yaml
shopware:
dal:
max_rule_prices: 200
But read the core’s own log message first — it’s unusually candid (CheapestPriceAccessorBuilder.php:36):
„You can increase the dal.max_rule_prices, but this will have a negative performance impact. Consider restructuring your rules, so that not so many match at the same time.„
The JSON accessor SQL grows with every active rule; at some point every listing query pays for your rule sprawl. So the honest fix list is:
- Audit rules: rules that don’t influence prices don’t need price conditions; rules that can never apply together shouldn’t all match the same context.
- Raise the limit as a stopgap, and measure listing performance before/after.
- Add monitoring for the log message above — it’s the only signal you get, treat it like the alarm it is. (Ironically, the previous post in this series was about making log noise quieter — this is one line you want loud.)
TL;DR
If more than shopware.dal.max_rule_prices (default 100) rules are active in a customer’s context, Shopware silently considers only the first 100 for price sorting and filtering — prices display correctly, but listings sort/filter on stale defaults for the rest. The only symptom is a log warning. Grep for it, alert on it, and restructure rules before reaching for the config knob.
Next up: customer impersonation — the undocumented Store API route that lets an admin browse and order as any customer.
If you’ve hit this limit in the wild, drop me an email — I collect these stories!
Found in Shopware 6.7.0.0: Framework/DependencyInjection/Configuration.php:519 (default 100), truncation and warning in Content/Product/DataAbstractionLayer/CheapestPrice/CheapestPriceAccessorBuilder.php:32-38, wiring in Content/DependencyInjection/product.xml:525.
Other articles from this category