RAM PRIX
Methodology
Two related things live on this page: how we compare RAM kits on value ($/GB) right now, and how we track how RAM prices move over time (the RAM Price Index). Every number below is either a fixed threshold in our code or a figure measured directly against our production database β nothing here is an estimate.
$/GB: our only value metric
Every kit's value comes down to one number: its lowest listed price divided by its capacity in gigabytes. Lower $/GB is a better deal β full stop. We don't blend in a separate performance or "value" score; $/GB already answers the buyer's question directly.
But $/GB only means something next to comparable kits. A 16GB DDR5-6000 desktop kit and a 8GB DDR4-2400 laptop kit aren't peers, so we group kits into buckets before comparing $/GB within a group: category (desktop / laptop / server) Γ memory type (DDR4 / DDR5) Γ speed grade.
Speed grade is a measured ladder, not an arbitrary cut: DDR4 splits at β€2666 / 2933β3200 / 3466β3600 / >3600 MT/s, and DDR5 at β€5200 / 5600β6000 / 6200β6400 / >6400 MT/s. Those boundaries sit at the real clusters in our catalog (masses at DDR4 3200/3600 and DDR5 5600/6000/6400, with only a thin tail of boutique overclocked kits above), not round numbers picked in advance.
We bucket on category, deliberately not on the catalog's form_factor field. form_factor is free text pulled from listings, and desktop UDIMM alone shows up spelled at least four different ways ("UDIMM", "288-pin UDIMM", "288-pin U-DIMM", "288-pin UDIMM, low-profile (33.2mm height)"). Bucketing on it directly would split one real peer group into several near-empty slivers and rank kits against too-small a sample. category is clean β exactly three values, desktop / laptop / server β so that's what we key on.
The RAM Price Index
The index answers a narrower, more honest question than "what does RAM cost": how much did the price of the same kits change from one month to the next? Every month, we look only at kits (specifically, a model in a given region) that were priced in both that month and the prior month β a "matched-model" comparison. A kit entering or leaving the catalog can't move the index; only a real price change on something we could see in both months can.
For every matched kit we compute the ratio of this month's price to last month's. A single kit spiking or crashing 10x (a data error, a clearance blowout, a currency glitch) shouldn't swing the whole index, so before averaging we clip β winsorize β each ratio to the range [0.667, 1.5]. Anything outside that band is pulled back to the nearest edge rather than dropped, so an extreme price still counts as "up" or "down", just not by an implausible multiple.
We then take the geometric mean of the winsorized ratios β a Jevons index β and multiply the previous month's level by that mean to get this month's level. The index is fixed at 100 in Sep 2025, the earliest month with full coverage across every region we track (that's also as far back as we can go: our upstream data provider only retains about a year of raw daily observations, so Sep 2025 is a hard floor, not a stylistic choice).
Three guardrails keep a thin or noisy month from producing a level we don't trust:
- MIN_LISTINGS = 2 β a single day's price for a kit only counts if at least 2 listings back it. Measured against production: this alone excludes about 76% of daily (model, region) price cells, so it is a real filter, not a formality.
- MIN_PRICED_DAYS = 10 β a kit needs at least 10 priced days within a month for that month's price to count at all. About half of (model, region, month) groups fail this bar.
- MIN_BASKET = 30 β if fewer than 30 kits survive both filters and matched into the prior month, we don't trust that month's link at all: we carry the previous level forward unchanged instead of computing a fresh (and statistically noisy) one. In practice this floor has plenty of headroom β every complete month we've measured has landed with 93β147 matched kits, 3β5x over the 30 floor.
MIN_LISTINGS and MIN_PRICED_DAYS apply to every series above, including $/GB β a kit's $/GB for a month is built from the same filtered daily prices. MIN_BASKET is different: it is specifically the "matched into the prior month" guard for the two chained series, so it doesn't gate $/GB, which by design looks at every kit priced that month rather than only the ones matched to the month before.
All of the figures above are measured against our production database, not assumed β see docs/measured-constants.md for the underlying queries and full results.
We publish three series, and only two of them are built the way described above. The median matched price and the lowest matched price (a proxy for the best deal available that month, not the typical one) are both matched-model, chained indices: same basket, month over month, exactly as described in this section.
The median $/GB series is deliberately different: it is cross-sectional, not matched-model. Every month, we take the median of price Γ· capacity_gb across every kit priced that month β not just the ones we can match to the prior month β and rebase it to 100 at Sep 2025. A matched-model index like the two above holds the basket fixed on purpose, so a shifting product mix can never masquerade as a price move. $/GB does the opposite on purpose: if cheaper high-capacity kits show up in the catalog, the typical cost per gigabyte falls even if not one single kit's price changed. For a memory site that is the more useful number for a buyer, because it answers "what does a gigabyte cost right now" rather than "how much did this fixed basket's price move." The two numbers will usually move together but are not required to, and won't whenever the capacity mix of what's actually being sold shifts.
The most recent calendar month is treated differently: with fewer than 10 priced days recorded so far, it can't clear MIN_PRICED_DAYS, so its basket comes back empty and its level is the prior month's, carried forward. We mark that month provisional everywhere it appears and leave it out of the index chart's line entirely, rather than plot a level we know isn't a fresh reading.
Where the data comes from
We track listings across six regions (US, Canada, UK, Germany, France, Spain) from Amazon's and Newegg's storefronts in those markets. Upstream scraping is manual and unscheduled β there is no cron guaranteeing a fresh observation on any particular cadence β so a listing's price can be anywhere from a few days to a few weeks old at any given moment.
Measured against production: the median listing's current price is about 5.6 days old, 90% are under 19.5 days, and 95% are under 23.5 days old, with a long tail out to 46 days for the slowest-moving listings. We consider a price stale, and stop showing it as current, after 30 days β comfortably past the p95, with headroom for that structural long tail.
UK and Germany: no stored price history
Amazon's UK and Germany Associates programs do not permit storing pricing history beyond 24 hours or surfacing price-drop alerts. To stay compliant, we simply don't do either for those two regions: kit pages for the UK and Germany show only the current price, with no stored price-history chart, and there is no price-tracking claim made for those markets. The RAM Price Index itself is a global, cross-region figure and is unaffected β this restriction is specific to per-region price history.