Build1 publisher3 min readPublished
A pricing policy built to resist promos never reads its promo label
A dev.to post rebuilds naive competitor price matching as a five-step control loop whose guards are a comparability filter, a margin floor and a cap on how far a single run may move a price.
The Engineer · Build desk

What happened
- A dev.to post reframes competitor price matching as a five-step control loop: observe prices, normalize the observations, decide whether they matter, apply a change, then measure what happened.
- Its starting example returns the minimum of scraped competitor prices and, by the author's own list, ignores shipping, stock, coupons, minimum advertised price rules, condition and seller reputation.
- The failure walk-through has a competitor clearing a SKU from $299 to $249, the matcher following, a second competitor matching that, and the $249 sticking because nothing marked the signal temporary.
- The Python policy drops out-of-stock, used and slow-delivery offers, floors the price at unit cost divided by one minus the target margin, and limits how far a single run may cut the price.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint The per-run change cap works as a delay as much as a margin guard: a transient clearance gets several runs to expire before the policy fully matches it, and a single bad scrape costs one capped step instead of the full drop.
- contradiction A team copying the sample inherits the exact leak the post opens with, because no predicate in the code tests promo_label.
- decision Anyone adopting the schema has to settle whether a coupon counts toward landed price, since the table records coupon_value and the comparison function sums only checkout price and shipping.
- exposure A silently failing extractor reaches the pricing engine as market data, so the team that owns the scraper owns a margin bug.
The last line of `recommended_price` is what bounds the damage in time. It returns `max(target, lowest_allowed_today)`, and `lowest_allowed_today` is the current price minus a fixed fraction of the current price [18]. Pick 5 percent for that fraction, since the post does not specify one, and re-run the opening example. A competitor clears a SKU from $299 to $249 [7]. The policy prices at 284.05, then 269.85, then 256.36, then 249 on its fourth run [22]. The one-line matcher the post calls "easy to explain and dangerous to run" [5] gets there on the first [4]. If the clearance ends before the fourth run, the match never completes. The $299 case is an illustration; the post does not report how often any of this happens in the field.
`floor_price` divides unit cost by one minus the target margin [17]. At a unit cost of 200 and a `min_margin_pct` of 0.2, the floor is 250, and 50 on 250 is a 20 percent margin on the selling price [23]. The formula I more often find in pricing code, cost times one plus margin, returns 240, whose actual margin is 16.7 percent [26]. The two guards also compose in the right order: the final `max` can only return a price at or above `target`, so the change cap cannot pull a price under the margin floor [27].
One `price` field becomes a 17-column observations table, four columns of it money [8][9]. `scrape_status` and `raw_payload` are declared NOT NULL; `shelf_price`, `checkout_price`, `shipping_price`, `coupon_value` and `in_stock` are not [10]. A failed scrape lands as a row with a status and no price. Step 3 of the loop can then distinguish an absent offer from an absent scrape [2].
The gap is `promo_label`. It is a field on the `Offer` dataclass [19], and no function in the sample reads it [20]. `is_comparable` tests `in_stock`, `product_condition` and `delivery_days` [16], and the margin leak the post opens with is a weekend promo [1]. `coupon_value` has the same problem from the other direction: it is a column in the table [8], it is not a field on `Offer`, and `landed_price` adds checkout price and shipping without subtracting anything [15][21]. The post is direct about the stakes, saying an extractor that misses coupons or silently fails on checkout pages leaves the pricing engine receiving false market data [12], and it recommends Wire for extraction jobs that return promotion details and failure states instead of only a shelf-price field [13].
`market_price` is still a `min()`, now taken over whatever survives `is_comparable` [18]. The filters change which rows are eligible; the aggregation is unchanged, so one listing that is in stock, new and quick to deliver can set the target [25]. When nothing is comparable, the function returns the current price [18], so a market that has gone out of stock cannot move a price up.
Step 5 has no code in the sample. `landed_price` normalizes, `is_comparable` decides, `recommended_price` applies, and nothing measures what the applied change did [24]. The post's own advice is to write down the rules a human pricing manager would enforce before reaching for machine learning [14].
What to watch
- Whether a follow-up adds step 5: a path that attributes realised margin and units to each applied price change.
- Whether the Offer dataclass gains a coupon field and is_comparable gains a promo_label test.
- Any published figures on how often out-of-stock or coupon-gated observations trigger a match in production.