/
Omnibus Pricing Without the Panic

ArticleOmnibus Pricing Without the Panic

If you run an online shop in the EU and you show a discount, you are required to show the lowest price the product had in the 30 days before the reduction. That is the short version of what the Omnibus Directive (EU 2019/2161) did to the Price Indication Directive, and in Germany it landed in §11 PAngV. The strikethrough price next to your sale price is not decoration anymore. It is a regulated claim, and regulators and competitors' lawyers both read it.

Most shops I see handle this late and nervously. The promotion engine gets built first, the legal requirement gets bolted on afterwards, and suddenly the frontend is doing price archaeology at render time: fetching history, computing minimums, praying the cache is warm. That is the panic version.

The calm version treats the 30-day low as what it actually is: a property of the product, not a property of the page.

Make it a data property

In a recent multi-market commerce build (six countries, six currencies, a catalog in the hundreds of thousands), we put the rule into the data pipeline instead of the UI:

  1. Price history is a first-class table. Every price change writes a row: product, market, price, timestamp. Boring, append-only, auditable. This table is the legal ground truth, and it exists whether or not anything is currently on sale.

  2. The 30-day low is computed at ingest, not at render. Whenever a price changes or the daily job runs, the pipeline computes the rolling 30-day minimum per product and market. It is one window query over the history table.

  3. The result lives in the search document. We index the 30-day low into the search engine document right next to the current price. Product lists, search results and product pages all read one document and have everything they need to render a compliant price block. No extra lookups, no N+1 on category pages, no separate "compliance API".

The frontend logic collapses to a single presentational question: is the current price lower than the reference price? If yes, show both, labeled correctly for the market. The frontend never computes anything legally meaningful, which is exactly how it should be. Rendering code changes weekly. Legal claims should not depend on it.

The edge cases are policy, not code

The implementation is the easy 80 percent. The remaining 20 percent are questions your lawyer and your merchandiser have to answer once, and then the pipeline enforces forever:

  • New products have no 30-day history. Decide the rule (no reference price shown until history exists) and encode it.
  • Progressive discounts (a sale that gets deeper) may reference the price before the first reduction, depending on the market's interpretation. That is a per-market flag, not a rewrite.
  • Each market can differ. The rule is EU-wide but national transpositions and enforcement practice vary. Because the low is computed per market anyway, market-specific policy is one branch in one place.

The pattern generalizes past Omnibus. Any regulated display value, energy labels, unit prices, deposit amounts, behaves better as ingested data than as rendering logic. Compute it where the data lives, store the result where the frontend already looks, and compliance stops being a project. It becomes a column.

If your shop is staring at an Omnibus retrofit right now, the honest first step is not touching the UI at all. Start with the price history table. Everything else follows from having the ground truth in one place.