Skip to content

Build1 publisher3 min readPublished Updated

Scoring 300 candidates in 35 milliseconds forces the LLM out of the request path

A dev.to post lays out a four-layer recommender and a 100 millisecond p99 budget with no slot for a generative call in the hot path. The figures are its author's own allocation, not a measurement from a running system.

The Engineer · Build desk

Illustration accompanying Scoring 300 candidates in 35 milliseconds forces the LLM out of the request path

What happened

  • A dev.to post takes apart the pitch of sending a catalog and a user's history to a model and deleting the recommender, saying it demos on 200 items and falls over at 400,000 with 80 milliseconds to answer.
  • It splits a recommender into four layers: data and features, candidate retrieval, ranking, and feedback and experimentation.
  • The LLM is placed inside layers two and three, doing semantic feature extraction and deciding what evidence to retrieve, with the final ordering left to a deterministic scorer.
  • Roughly 80 percent of the project effort goes into the data and features layer, according to the post, whether a team builds it or buys it.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint With 75 of the 100 milliseconds already committed to fetch, retrieval, scoring and rules, a per-request model call has to share 25 milliseconds with the network.
  • decision Putting a model anywhere near the hot path means building the timeout and the deterministic fallback first, because a hung call shows the user an empty strip.
  • cost Teams that logged clicks but not impressions pay for every ranker change in live A/B traffic, since replaying logged traffic against a new ranker is no longer possible.
  • contradiction The papers offered as support argue about what generative recommenders optimise against; the catalog-scale and latency limits rest on the author's own budget allocation.

Divide the 35 millisecond ranking line by the roughly 300 candidates it scores and the per-item cost is about 0.117 milliseconds [2]. The 300 candidates are scored in one batched pass over the shortlist. For the number to transfer to another stack, item embeddings have to exist before the request arrives, the user vector and recent events have to return from cache inside the 5 milliseconds allotted, and the ANN index has to be resident in memory [9][10].

The five stages sum to 75 milliseconds against the stated 100 millisecond p99, leaving 25 milliseconds for network and queueing [1]. The post's opening uses a tighter deadline, 80 milliseconds, and on that figure the slack is 5 [1][3]. Neither figure has room for a generative call in the request path, so the LLM work moves elsewhere: embeddings generated at ingestion, query understanding cached per distinct query, evidence selection decided asynchronously and reused [10]. When a model genuinely has to run per request, the author keeps it to a shortlist of tens, behind a timeout, with a deterministic fallback [11]. A strip that degrades to a popularity-ranked list is fine; one that returns nothing because a model call hung is a broken page, the post says [12].

Those timings are the post's own worked example [9]. The two 2026 papers it cites support a narrower point. RecoChain, given as arxiv 2604.25787, proposes unified generative retrieval and ranking and is then evaluated against classic top-k ranking metrics, because the measurement requirement does not go away [3]. RRCM, arxiv 2605.07129, frames LLM recommendation as retrieval-and-reasoning, where the model decides when to pull more evidence and optimization still runs against the final ranking reward [4].

The most common data-layer mistake, according to the post, is recording what users clicked without recording what they were shown [20]. The impression row it proposes is seven fields wide: request_id, user_id, item_ids, positions, ranker_version, retrieval_source and a timestamp, with interactions joined back on request_id [13][4]. Without that row you cannot compute a click-through rate, correct for position bias, or evaluate a new ranker counterfactually against logged traffic [14]. Online A/B testing becomes the only way to learn anything, and the post calls that slow and expensive [14]. The per-item retrieval_source is the diagnostic field: when quality drops, it tells you whether the collaborative path or the embedding path produced the bad candidate [15].

Recall@k asks whether the item the user eventually chose made the shortlist at all, NDCG@k asks how the shortlist was ordered, and a ranking model cannot fix a candidate set that never contained the right item [16].

Matching two sides of a marketplace runs the same four layers with two changes. Mutual constraints mean a candidate has to clear both sides' filters, so the retrieval layer runs twice and intersects [17]. Supply also exhausts: recommending the same top-rated contractor to 400 buyers produces 399 disappointments, so the ranking layer needs a fairness or throttling term [18]. Pure item recommendation gets by without one.

What to watch

  • A published serving trace showing a generative ranker inside a sub-100ms p99 on a six-figure catalog would undercut the allocation argument.
  • Whether follow-ups to RecoChain and RRCM report end-to-end serving latency alongside their offline top-k metrics.
  • Any measurement of what a fairness or throttling term in the ranking layer costs in conversion on a two-sided marketplace.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories