case study · ranking & recommendations

Putting Relevant Products First

Use purchase history to help returning shoppers find what they are likely to need again.

← Systems we builtCase study

The problem

A returning grocery shopper has bought many products before. Which should appear first when they build their next basket? Showing everything in purchase-history order wastes attention.

What we built

The model ranks products the shopper has already purchased, using signals such as frequency, recency and order history. Features use only information available before the order being predicted. The goal is to put likely repeat purchases near the top.

See a shopper’s recommendations

Choose a held-out shopper and run the ranking. The list shows product names, model scores and how often each product was bought before.

Rank a Shopper

Choose a held-out shopper to rank their previously purchased products.

Shoppers are real holdout users the model never trained on. Ranking runs against the live model API.

How we tested it

We compared the model with two simple alternatives: most frequently purchased first, and a combination of purchase frequency and recency. The evaluation asks whether products the shopper actually reordered appear near the top. NDCG rewards both relevance and position; recall measures how many reordered products were found.

Evaluation offline holdout

Relevance improved over a frequency-and-recency baseline.

NDCG@10: 0.549 vs 0.518 baseline; 12,231 held-out shoppers.

Offline relevance only; purchase, conversion and revenue impact were not measured.

Evaluation data →

What the result means

The model improved the ordering over the stronger frequency-and-recency baseline. That supports testing it in a product. Whether it helps customers complete baskets or increases purchases still requires a live experiment.

Benchmark and evaluation notes

Results

NDCG@10, 12,231 Held-Out Shoppers
0.00.20.40.6 0.501 0.518 0.549 FrequencyFrequency+ recencyModel Ranking method NDCG@10
Recall@10, Same Shoppers
0%20%40%60% 52.5% 54.4% 57.8% FrequencyFrequency+ recencyModel Ranking method Recall@10
MetricLambdarankFrequency + Recency BaselineFrequency Baseline
NDCG@100.5490.5180.501
NDCG@200.6050.5760.557
Recall@1057.8%54.4%52.5%
Recall@2075.5%72.5%70.2%

Measured on 12,231 shoppers held out of training (890 more were excluded for having no candidate product they went on to reorder). The frequency baseline ranks by how often a product was bought before; the frequency + recency baseline also favors products bought recently. Lambdarank beats the stronger baseline on every metric, by 0.031 on NDCG@10 (95% interval on the model: 0.544 to 0.553). These are offline ranking results on held-out orders, not conversion or revenue lift.

Orders
3,421,083
Order Lines
33,819,106
Shoppers
206,209
Products
49,688

Code

The model, the training pipeline, and the scoring service: github.com/alphan-ml/reorder-radar

Where It Runs Data, deployment and checks
Where It Runs
ComputeAWS Lambda behind API Gateway, us-east-1. Function reorder-rank-user. Endpoint fmyrmgb4h1.execute-api.us-east-1.amazonaws.com.
ModelLightGBM Lambdarank model and the held-out shopper features it ranks with. Read from S3 (giggit-reorder-radar-models) at cold start.
DeployA merge to main runs the tests, swaps the handler in the Lambda, and checks /health. GitHub Actions with an AWS role; no stored keys.
ChecksEvery six hours a job scores 200 held-out shoppers against this endpoint and writes the result to a public ledger. Live Checks.