← Back
Home › Systems › AI applications

recommender

Chooses a few items out of millions to show a person, using candidate generation followed by ranking.

TikTok, YouTube

Open the recommender pagerecommender Count-min sketchdata-structures: d rows of w counters estimate any item's frequency in a stream, overestimating by at most ε·N with probability 1-δ, in fixed tiny memory.›Windowed stream aggregationdistributed: Group events by event-time window per key, keep one partial aggregate per slice, and emit a window when the watermark passes its end.›Calibrationmachine-learning: Make predicted probabilities match observed frequencies: measure with ECE, fix post hoc with temperature, Platt or isotonic scaling on held-out data.›Matrix factorization forcollaborative filteringmachine-learning: Learn a short latent vector per row and per column from the observed cells only; a missing cell is predicted by the dot product of its two vectors.›Contrastive learningmachine-learning: Train an encoder so two views of the same thing score higher than every other pair in the batch; InfoNCE with a temperature, no labels needed.›Embeddingsmachine-learning: A learned table mapping discrete ids to dense vectors: gather forward, sparse scatter-add backward, row-wise optimizers to keep huge tables cheap.›Evaluation metricsmachine-learning: Precision, recall, ROC AUC, average precision, log loss, NDCG and pass@k computed correctly, plus paired confidence intervals for comparing models.›Feature interaction modelsmachine-learning: Click/conversion prediction networks for ranking: feature crosses (DCN, DeepFM), embedding bags, calibrationFeature storemachine-learning: One definition per feature feeds a history store for training and a latest-value store for serving, so training and inference see the same values as of the same moment.›Multi-armed banditsmachine-learning: Choose among K options repeatedly while learning their payoffs: epsilon-greedy, UCB1 and Thompson sampling keep total regret low where a fixed split or a fixed exploration rate pays forever.›Negative samplingmachine-learning: Train by contrasting each observed positive with a few sampled negatives instead of normalising over every candidate; the choice of sampler decides bias and quality.›Two-tower retrievalmachine-learning: Two separate encoders map users/queries and items into one vector space; item vectors are precomputed and searched by nearest neighbour, so recall over millions costs one small forward pass.›Embedding table shardingml-training: Sharding huge embedding tables across devices (row/column/table-wise) with all-to-all lookups and cachingTransformer blockml-training: The decoder-only pre-norm block (attention plus MLP on a residual stream) behind every modern LLM, with exact shapes, parameter, FLOP and KV-cache counts.›HNSWsearch-sort: Hierarchical Navigable Small World: a layered proximity graph searched greedily from a sparse top layer; the default in-memory approximate nearest-neighbour index.›IVF-PQsearch-sort: Inverted file plus product quantization: cluster vectors into lists, store each as a few bytes of codes, scan only the nearest lists via table lookups.›Maximal marginal relevancesearch-sort: MMR and other diversification re-ranking of result listsTop-k selectionsearch-sort: Keep the k best of n items without sorting all n - bounded min-heap for streams, quickselect for arrays, threshold pruning to skip most items.›A/B testing (online controlledexperiments)statistics: Randomly split units into arms by a salted hash, log exposure, compare metrics with a confidence interval, and guard the result with sample-ratio, guardrail and peeking checks.›Fast hash functionsdata-structures: Non-cryptographic hashes built from 64×64→128-bit multiplies and xor-shifts; pick by key size, trust level and whether the hash is persisted.›Watermarksdistributed: Event-time progress markers that bound lateness and trigger window resultsHash aggregationstorage: GROUP BY via hash tables with partitioning and spill to diskHierarchical timing wheelsystems: Timers bucketed by expiry into wheels of slots, coarser wheels for far deadlines: O(1) insert and cancel for millions of timeouts.›Linear and logistic regressionmachine-learning: Fit a weighted sum of features to a number (least squares) or a probability (logistic); the baseline every model must beat.›LU and Cholesky factorizationnumerics: Factor A = PLU (any square matrix, partial pivoting) or A = LLᵀ (SPD) once in O(n³), then solve each right-hand side in O(n²).›Sparse matrices (CSR)numerics: Compressed sparse row stores only nonzeros as row pointers, column indices and values; SpMV streams them once, so it is memory-bandwidth bound.›Data augmentationmachine-learning: Generate label-preserving variants of each training example on the fly to enlarge the effective dataset and bake in invariances.›LSM-treestorage: Buffer writes in memory, flush them as immutable sorted files and merge in the background; turns random writes into sequential I/O.›Loss functionsmachine-learning: The scalar a model minimizes: cross-entropy for classes and tokens, MSE or Huber for values, each with a stable form and simple gradient.›AdamWml-training: Adam's per-parameter adaptive steps with weight decay applied directly to the weights; the default optimizer for transformers and LLM pretraining.›Reverse-mode automaticdifferentiationml-training: Record the forward computation on a tape, then sweep it backwards once to get the gradient of a scalar loss for all inputs.›+ 16 moreConsumer offsetsdistributed: Each consumer group stores one integer per partition, the next position to read, so a restarted consumer resumes where it left off with at-least-once delivery.›Slab allocatorsystems: Pre-carve pages into equal-size slots per size class with an in-place free list: O(1) alloc and free, no external fragmentation, cache-warm reuse.›L-BFGSnumerics: Quasi-Newton minimizer that approximates the inverse Hessian from the last m gradient differences via the two-loop recursion; O(m·n) memory and work per step.›+ 5 moreFencing tokensdistributed: A number that grows with every lock grant and is checked by the protected resource, so a paused ex-holder's late write is rejected.›Message sequence numbersdistributed: A per-stream counter on every message lets the receiver detect loss, duplicates and reordering, ack cheaply and resume after reconnect with "send from N".›Segmented logdistributed: Split an append-only log into files named by their first offset, write only the newest, and find any record by binary search plus a sparse index.›+ 1 more

How it is built

Architecture overview

A recommender answers one question per request: out of millions of items (videos, posts, products), which few should this person see now, in what order? Scoring every item with a big model is impossible inside a request, so the system is a funnel. Cheap candidate generators cut millions to a few thousand; a ranker with rich features scores those; a re-ranker arranges the winners for variety and for learning; the page is served. YouTube's paper describes exactly this split as the classic two-stage dichotomy of a deep candidate generation model and a separate deep ranking model (source: Covington et al., Google Research page), and X's open-sourced home timeline follows the same layering with candidate sources, a light ranker, a heavy ranker, and mixing and filtering (source: twitter/the-algorithm README). The idea that makes it work is that every stage speaks in vectors and probabilities: users and items live in one embedding space that approximate-nearest-neighbour search can query in milliseconds, and the ranker's outputs are calibrated probabilities that can be combined into one value per item. Everything else (streams, a feature store, experiments) exists to keep what the models see in training identical to what they see when serving, and to prove that a change helps.

Parts:

 client ─► feed service ─► candidate sources ────────────────► ranker ─► re-rank ─► page
 (user id,  (context)      ├ two-tower ► ANN index (HNSW/IVF-PQ)  │   (calibrated   (MMR, bandit
  context)                 ├ follow graph / in-network            │    p(click),     slot, rules)
                           ├ item-item / popular                  │    p(like) …)        │
                           └ fresh / exploration                  │                      │
                                  ▲ ~10^3 each                    ▲ ~10^2-10^3          ▼
                         item vectors (from item tower)     features: feature store      impression log
                                  ▲                          (latest values) ◄── stream aggregates
                                  │                                                      │
 training: logs ─► point-in-time joins ─► towers + ranker ─► export ─► re-embed items ─► rebuild index

How the parts fit together

Event stream and aggregates

Every impression, play, skip, like and hide is an event. Windowed stream aggregation groups events by event-time window per key (user, item, creator) and emits a window when the watermark passes its end: "plays of item X in the last hour", "this user's skips today". Windows are slices of partial aggregates, so a sliding window costs one add and one subtract. Contract: late events are the norm (mobile clients batch their uploads), so the watermark and the allowed lateness decide how fresh the number is versus how complete. Heavy-tailed keys (every item, every search term) do not all deserve exact counters, so a Count-min sketch keeps approximate frequencies in fixed memory, with a bounded overestimate; it is used for item popularity, for "how many times has this user seen this creator", and, as below, to correct sampling bias in training.

Feature store

The Feature store gives each feature one definition that feeds two stores: a history store for training and a latest-value store for serving. Its job is point-in-time correctness: a training row for an impression at 10:03 must contain the feature values as they were at 10:03, not today's. A model trained on leaked future values scores well offline and badly online (training-serving skew). The contract with the ranker is a flat list of named features with types and a freshness class (real time, hourly, daily).

Candidate generation

Two-tower retrieval encodes users (history, context) and items (id, content, creator) into one vector space with two separate networks. Item vectors are computed offline, so serving costs one user-tower forward pass plus a nearest-neighbour search. Both towers lean on Embeddings, learned tables from ids to dense vectors. A user tower that reads a long sequence of recent items usually does so with a Transformer block over the history.

The towers are trained with Contrastive learning: the pair (user, item they engaged with) should score higher than that user against every other item, with an InfoNCE loss and a temperature. Doing the softmax over the full corpus is too expensive, so Negative sampling contrasts each positive with a few sampled negatives, and the cheapest sampler is the other items in the same batch. That sampler is biased in a power-law corpus (popular items appear as negatives far more often than rare ones), and the YouTube retrieval paper corrects it by estimating item frequency from the stream (Yi et al., RecSys 2019); a count-min sketch is the textbook alternative for that estimate. Embedding-based retrieval has the same shape outside video: Facebook's search paper describes serving it inside an inverted-index based system (Huang et al. 2020).

Matrix factorization for collaborative filtering is the older alternative: learn a vector per user and per item from the observed cells, and predict by dot product. It is simple, fast to train, and still a good baseline source, but it has no vector for an item that nobody has touched yet, and a content tower does. Real systems run several sources side by side (two-tower, follow graph, item-to-item, popular in region, fresh uploads) and merge the lists by id; X reports that about half of home-timeline posts come from its in-network source (source: twitter/the-algorithm README).

Vector index

Item vectors are searched by approximate nearest neighbour. HNSW is a layered proximity graph searched greedily and is the default in-memory index: high recall at low latency, but the graph and the full vectors must be in RAM. IVF-PQ clusters vectors into lists and stores each as a few bytes of product-quantisation codes, scanning only the nearest lists; it needs far less memory per vector at some recall cost. The choice is a memory-versus-recall trade-off at corpus size; Faiss implements both families. Top-k selection (a bounded heap) keeps the best candidates across lists and across shards.

Contract: the index and the user tower are a matched pair. Vectors from model version N are only comparable with queries from version N. A model release therefore re-embeds the corpus and builds a new index before traffic moves, and the serving layer must never mix versions.

Ranker

The ranker sees a few hundred to a thousand candidates (order of) and can afford many more features per candidate than the retrieval stage: user history aggregates, item stats, creator stats, user-item crosses, context. Click and conversion prediction here is a sparse-feature problem: feature-interaction-models (no page yet) holds the model families that learn feature crosses (DCN V2 is one: it learns bounded-degree feature interactions, Wang et al. 2020; Wide & Deep joins a memorising wide part with a generalising deep part, Cheng et al. 2016). Click-probability prediction (CTR models) and Deep ranking models for recommendation are the pages for the individual models. Id features are huge, so they pass through Feature hashing (the hashing trick) into embedding tables, which are the memory problem of this part: DLRM splits it by using model parallelism for the embedding tables and data parallelism for the dense layers (Naumov et al. 2019), and embedding-table-sharding (no page yet) is the technique. ByteDance's Monolith replaces hashing with a collisionless embedding table, with expirable embeddings and frequency filtering to bound memory, so two ids never share a vector (Liu et al. 2022).

One ranker usually predicts several outcomes (click, watch time, like, share, hide), because optimising a single click rate rewards clickbait; YouTube's multitask ranking paper treats competing objectives and implicit selection bias in user feedback as the core difficulty (Zhao et al. 2019). The heads are then combined by a weighted sum into a value. That sum multiplies probabilities, so each must be calibrated: Calibration fits a map such as isotonic or Platt scaling on held-out data so that a predicted 0.1 means about 10 % of such items get the outcome. Otherwise changing one head's training data silently re-weights the whole objective.

Re-ranker and exploration

Sorting by value gives a page of near-duplicates: ten videos from one creator, ten angles on one topic. maximal-marginal-relevance (no page yet) picks items greedily by relevance minus similarity to what has been picked. Business rules sit here too (age limits, blocked creators, per-creator caps).

Exploration is the other job. A new item has no history, so the ranker underrates it and it never collects any. Multi-armed bandits allocate a share of slots to uncertain items (UCB or Thompson sampling) so their payoff becomes known and so the data the next model trains on is not only what the current model already liked. The alternative, a fixed exploration rate, pays the same cost forever. Contract: every exploration slot logs its propensity, so training can correct for it.

Evaluation

Offline, Evaluation metrics measure retrieval (recall at k of held-out engagements), ranking (NDCG, AUC, log loss) and calibration (ECE), with paired confidence intervals so a 0.2 % gain is not noise. Offline numbers only qualify a change; they do not prove it, because the data was produced by the previous model. A/B testing (online controlled experiments) does: randomly split users into arms by a salted hash, log exposure, compare long-term metrics with a confidence interval, and guard with sample-ratio, guardrail and peeking checks. The alternative for allocating traffic while learning is the bandit; for product decisions that need a clean effect size, an A/B test is the tool.

Data and control flow

One feed request:

  1. The client sends user id and context; the feed service loads the user's latest features from the feature store.
  2. The user tower computes the user vector (or reads a cached one).
  3. Each candidate source returns up to a few thousand ids (order of): ANN search, follow graph, popular, fresh. Merge by id and drop what was already seen.
  4. The ranker scores the survivors; features are fetched in one batched lookup, because feature fetch, not the neural net, is often the largest part of ranking latency.
  5. Calibrated outputs are combined into a value; hard filters run (safety, blocked, age).
  6. The re-ranker applies diversity and exploration slots; the page is returned and every shown item is logged with its position, scores and propensity.

An interaction becoming a feature:

  1. A play event reaches the log; the stream job slots it into the user's and item's windows.
  2. Aggregates are written to the latest-value store and appended to the history store.
  3. The next request, seconds later, sees the changed counts; the next training run sees the same values as of the time.

A model refresh (daily to weekly, order of):

  1. Join impressions with outcomes and point-in-time features; train towers and ranker.
  2. Export; re-embed the whole corpus with the new item tower; build the new ANN index.
  3. Calibrate the ranker on held-out data, shadow-score live traffic, then ramp through an A/B test.
  4. Swap tower, index and ranker together.

Scaling

In the order they bite:

  1. Per-request compute. The funnel is the lever: each stage scores fewer items with a more expensive model. Moving the cut earlier saves the most, and costs recall.
  2. Embedding-table memory. Id features for users and items outgrow one device. Levers: hashing, collisionless tables with expiry and frequency filters, sharding by row or table across devices (TorchRec's purpose, "large embedding tables sharded across many GPUs"), and on the serving side quantised or cached rows.
  3. Index memory and build time. HNSW holds everything in RAM. Levers: IVF-PQ compression, sharding the corpus and merging per-shard top-k, filtering to recent or eligible items before indexing.
  4. Feature fetch latency. Levers: batch lookups, co-locate features by user, cache hot users, precompute the expensive ones.
  5. Freshness. Daily models miss what became popular this hour. Levers: stream aggregates as real-time features, online training of the sparse parameters (Monolith's design aim), a fresh-items source.
  6. Measurement. A/B tests need traffic and time. Levers: variance reduction, many layered experiments, offline replay for screening.

Failure modes

FailureSymptomCauseFix
Training-serving skewoffline metrics up, online flat or downtraining features computed differently from serving, or future values leakedone feature definition in the feature store; point-in-time joins; log served features and compare
Tower and index mismatchrecall collapses after a releasenew user tower queries an index built with old item vectorsversion the pair; swap together; reject mismatched versions at query time
Popularity biasthe same hits dominate; niches vanishin-batch negatives and click logs favour popular itemsfrequency-corrected loss, exploration slots, per-creator caps
Feedback loopthe system only shows what it already showedtraining data comes from its own past rankinglogged propensities, exploration traffic, holdout slice
Cold-start blind spotnew items never surfaceno history, ranker underrates themcontent features in the item tower, fresh-item source, bandit slots
Clickbait optimisationclicks up, retention downsingle-objective rankermulti-task heads, long-term metrics, hide and dislike signals as heads
Miscalibration driftvalue mix shifts with no code changeone head's distribution movedrecalibrate on fresh held-out data; monitor ECE per head
Hash collisionsstrange recommendations for rare idsdifferent ids share one embedding rowlarger or collisionless tables, frequency filtering
Late-event skewcounters undercount recent activitywatermark too eager for mobile uploadsallowed lateness; mark features with freshness class
Position-bias errorranker learns to prefer the top slotposition used as a training labelposition as an input feature at train time, fixed at serve time; randomised slice
Page of near-duplicatesuser sees ten similar itemsno re-rank diversificationMMR or a per-topic cap

Real implementations

namewhat it isrepolicencenotes
X recommendation algorithmthe home timeline's services and models: candidate sources, light and heavy rankers, mixing and filtering, SimClusters and TwHIN embeddingstwitter/the-algorithmAGPL-3.0most complete open picture of the whole funnel
MonolithByteDance's recommendation training framework: collisionless embedding tables, real-time trainingbytedance/monolithApache-2.0built on TensorFlow
DLRMreference deep learning recommendation model with dense and sparse inputs and parallelised embedding tablesfacebookresearch/dlrmMITbenchmark for ranking models
TorchRecPyTorch library for sparsity and parallelism in recommender models: sharded embedding tablesmeta-pytorch/torchrecBSD-3-Clausetraining and inference of large tables
Faisssimilarity search and clustering of dense vectors, including quantised and HNSW indexesfacebookresearch/faissMITthe ANN layer
Gorserecommender engine in Go with multiple candidate sources, rerankers and a dashboardgorse-io/gorseApache-2.0a smaller, integrated system
TikTok, YouTubethe closed reference systemsnoneclosedYouTube's design is described in the papers below

Sources

  • P. Covington, J. Adams, E. Sargin, Deep Neural Networks for YouTube Recommendations, RecSys 2016. Google Research
  • X. Yi et al., Sampling-Bias-Corrected Neural Modeling for Large Corpus Item Recommendations, RecSys 2019. Google Research
  • Z. Zhao et al., Recommending What Video to Watch Next: A Multitask Ranking System, RecSys 2019. Google Research
  • M. Naumov et al., Deep Learning Recommendation Model for Personalization and Recommendation Systems, 2019. arXiv
  • Z. Liu et al., Monolith: Real Time Recommendation System With Collisionless Embedding Table, 2022. arXiv
  • J.-T. Huang et al., Embedding-based Retrieval in Facebook Search, 2020. arXiv
  • R. Wang et al., DCN V2: Improved Deep & Cross Network and Practical Lessons for Web-scale Learning to Rank Systems, 2020. arXiv
  • H.-T. Cheng et al., Wide & Deep Learning for Recommender Systems, 2016. arXiv
  • J. Johnson, M. Douze, H. Jégou, Billion-scale similarity search with GPUs, 2017 (Faiss). arXiv
  • Y. Malkov, D. Yashunin, Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs, 2016. arXiv
  • X recommendation algorithm README (pipeline components, candidate sources). repo
  • TorchRec README (sharded embedding tables). repo

Similar systems

Share the most building blocks with this one.