Price compression: index your shelf out-the-door before you cut
4 min read
By BudAlly
Published Updated
Operators quoted in the trade press agree on one thing: "cutting prices too aggressively is the biggest mistake retailers make when prices fall." This is the procedure for cutting precisely instead.
The shape of the problem
US retail sales fell in 2025 for the first time on record, and the signature is everywhere: transactions up 6.5%, basket down 5.5% (Headset, year to June 2026). Michigan revenue fell 5.3% on a 2.1% unit decline. New Mexico flower went from $10.61 to $4.04 a gram in under three years. Oversupply — roughly 73M pounds of capacity against 50M of demand — means the pressure isn't going away.
Under compression, the pricing error is almost never "too high across the board." It's a handful of SKUs 15–20% above market while others sit below cost — and a blanket cut that fixes the first by destroying the second.
Step 1 — Put every price on the same basis
Competitor menus show prices three ways: pre-tax, tax-inclusive, or "as displayed" with no statement. Your own shelf price is pre-tax. Convert everything to out-the-door:
| State | OTD formula (retail) | Notes |
|---|---|---|
| California | shelf × 1.15 × (1 + local sales-tax rate) | 15% excise on retail; local rate by city — Sacramento ~8.75% [verify] |
| Michigan | shelf × 1.16 | 10% adult-use excise + 6% sales; the 24% wholesale tax is already inside your cost |
| New Mexico | shelf × (1 + 0.14 + local GRT) | 14% excise from Jul 2026; GRT by location code; medical exempt |
| New York | per OCM potency/weight-based rules | Different base; compute per product [verify] |
Record each competitor observation with its tax basis (pre-tax / tax-included / unknown) and convert. An "unknown" basis is excluded from the index until someone checks it.
Step 2 — Match SKUs, not names
"Blue Dream 3.5 g" at two stores can be different brands, different sizes, different forms. Match on brand + size + form; score the match; auto-accept at 0.90 and above; review 0.75–0.89; exclude below. In a 410-SKU store that typically yields 130–140 matched SKUs — enough for an index, not enough to reprice everything.
Step 3 — Index, then look at gaps by category
Basket index = your OTD basket of matched SKUs ÷ the market median OTD basket × 100. An index of 112 means you're 12% above the local median. More useful is the category split: in the demo tenant, vapes 121, concentrates 115, flower 108, edibles 104, pre-rolls 97. The problem is vapes and concentrates; flower is nearly at market; pre-rolls are already below it. A blanket 10% cut would have thrown away margin on pre-rolls and edibles and still left vapes 9% high.
Step 4 — Know the floor before you touch anything
Floor = landed cost + your margin floor (the demo uses 35%) + any state floor (New York's wholesale multiple is under verification). Landed cost includes freight and, in Michigan, the 24% wholesale tax. A proposed price below the floor is not a proposal; it's a markdown decision for a human with the reason attached.
Step 5 — Propose, approve, apply, confirm
Each proposal: SKU, current shelf → OTD, market median OTD with its source and sample size, gap, proposed shelf, margin after. Three from the demo:
| SKU | Shelf → OTD | Market median (source, n) | Proposal | Margin after |
|---|---|---|---|---|
| Blue Dream 3.5 g | $38.00 → $47.52 | $41.90 (licensed, 23 stores) | $34.00 → $42.52 | 57.4% |
| Live resin vape 1 g | $45.00 → $56.28 | $46.90 (network, k = 14) | $39.00 → $48.77 | 53.8% |
| Pre-roll 5-pack | $24.00 → $30.02 | $32.50 (licensed, 17) | no change — under market | — |
A person approves. On a POS with a price-write API the change is drafted there; on Dutchie it becomes a task ("change it in Dutchie, then confirm") and the next sync verifies it.
Where the data must come from
- Licensed market data — Headset or equivalent, where the license covers SKU-level internal use in your state.
- Your own checks — a budtender visiting three competitors on Tuesday and recording prices with the tax basis. Low-tech, defensible.
- Network medians — realized prices from state-system receipts across opted-in stores, shown only with 8 or more contributors, and never including rows from Dutchie-connected stores (its developer terms).
- Not scraping. Weedmaps, Leafly and Dutchie menus are protected by terms of service; Dutchie's developer terms ban it outright. Scraper-built datasets carry contract risk that survives the CFAA cases, and that risk sits next to your license. BudAlly rejects uploads with scraper provenance.
The discipline
Index monthly. Reprice weekly, by category, above the floor, with a source on every figure. Cut where you're high; hold where you're at market; raise where you're below and the velocity says you can. Compression is a reason to be precise, not a reason to be fast.
BudAlly's price intelligence does steps 1–5 on any POS from licensed data, your own checks and the k ≥ 8 network — see it on a Sacramento store.
Sources
- MJBizDaily — The cannabis industry is having a price-compression crisis · 2026–07
- NM CCD 2025 Demand Study (flower −62% per gram since 2022) · 2025–12
- Headset — Cannabis industry statistics (basket −5.5%, transactions +6.5%) · 2026–06
- Cannabis Industry Journal — What cannabis retail pricing is telling us about market pressure in 2026 · 2026
- Dutchie Developer Terms (no scraping, no aggregation) — summarized in BudAlly data-use rule DU-SCR-01 · 2026