0x00 한

Research / Cross-service topics

Feed diversity — the layer that deliberately breaks score-ordered sorting

Sorting only by ranker score produces runs of the same author, the same topic, and the same video. The diversity layer prevents such runs. There are five main approaches, and most services stack several of them.

  1. Decay: multiply the score of the nth item with the same key (such as author) by f(n) < 1. It is a purely pointwise approach that scores each item separately, and its computation cost is low.
  2. Greedy re-ranking (MMR, maximal marginal relevance): add the distance from already selected items to the score. The score depends on the state of the list selected so far.
  3. Slate optimization (DPP, determinantal point process): treat the bundle of items shown at once (the slate) as one set and maximize the determinant of that whole set. It is the most expensive and the most principled approach.
  4. Dedup: never show the same thing twice. It is closer to hygiene than to diversity.
  5. Calibration: match the genre and topic distribution of the list to the distribution in the user's history. The goal is "same proportions as the history" rather than "different from each other", so the goal itself differs. Netflix published the formula (see the Netflix section below).

However, comparing services with this list requires first checking whether each approach is published. All four of X's approaches (decay, MMR, DPP, dedup) can be read in source code, but Meta has never published any of the four at the algorithm level for its main feeds inferred. The corpus we examined is listed in the "Case: Meta" section below. This absence is itself the second finding of this note.

Case: X — uses all four

X's decay, MMR, DPP, and dedup approaches can all be read in public source code verified (Who Uses This). The 2025 Scala generation has MMR, a category penalty, and 6 dedup filters, and the 2026 generation has author decay, DPP, and 3 dedup filters verified (Who Uses This section). The 2026-10-14 commit released the training code of a learned slate decoder, but its serving switch is off by default verified (section 5).

1. Author-diversity decay (2026)

The 2026 generation's author decay multiplies a post's score by a multiplier that depends on its rank by score among posts from the same author, and this multiplier has a floor verified. The function that sets the multiplier is shown below verified — home-mixer/scorers/ranking_scorer.rs:186-188 (Gen3 0bfc279).

fn diversity_multiplier(decay_factor: f64, floor: f64, position: usize) -> f64 {
    (1.0 - floor) * decay_factor.powf(position as f64) + floor
}

Here position is the rank within the same author after sorting by score in descending order. It is not the position in the final feed verified — :198-214.

The design has two notable points.

  • There is a floor floor. With decay^n alone, the score of an author's 10th post converges to 0 and is effectively banned. With a floor, floor times the original score always remains however many posts there are. In other words, this decay is a penalty, not a per-author cap.
  • The values of decay_factor and floor are read from a FeatureSwitch (runtime configuration). In Gen3 (0bfc279) those values were not in the repo, and the defaults in the Gen4 (47c1bcd) mirror are AuthorDiversityDecay 0.5 and AuthorDiversityFloor 0.25 verified — home-mixer/params/param.rs.

In the first Gen3 public commit aaa167b (2026-01-20), this decay was a separate scorer, author_diversity_scorer.rs verified — aaa167b scorers/mod.rs. In 0bfc279 (2026-05-15), the decay moved into the ranking scorer; the file remained but was dropped from the scorers/mod.rs declarations verified — 0bfc279 scorers/mod.rs. The file was deleted in the Gen4 release commit 47c1bcd (2026-08-13) verified — file commit history.

2. MMR — 2025 Scala

The 2025 Scala generation's MMR adds to the relevance score a weighted minimum distance from the candidates already selected verified. Diversity is not applied to the front part of the list, and the computed result overwrites the original score in place verified.

The MMR score is computed with the formula below verified — DiversityRescoringFeatureHydrator.scala:102.

score = relevance + diversityWeight × minDistance(candidate, already selected)
  • The embedding dimension is 128 verified :32.
  • The distance is not cosine similarity but the L2 distance between L2-normalized embeddings verified :64-69.

Diversity is not applied at all to the top part. minDistance skips the distance computation and uses a default value when the condition below holds verified :92-93,102.

if (selected.isEmpty || selected.size < (1 - diversityRatio) * n) None   // → getOrElse(2.0)

That is, the default 2.0 is used not only "for the first candidate" but for all of the first (1-diversityRatio)×n items of the list. Because the constant 2.0 is added equally to everyone, that part keeps the pure relevance order. Diversity applies only to the later part of the list.

MMR overwrites every ScoreFeature value verified :28,70,91. It reads relevance from ScoreFeature and writes it back to the same slot. In other words, what is called the "ranker score" after this point is already a value mixed with diversity.

The same generation has a separate category version. It applies a greedy penalty using the category counts of SimClusters (clusters that split the follow graph into communities), and the computation is the two lines below verified — CategoryDiversityRescoringFeatureHydrator.scala:69,72.

penalty += math.log(cnt + 1) / math.log(2)          // log2(cnt+1)
score = math.max(relevance - weight * penalty, 0.00001)

MMR adds to the score, and the category version subtracts from it. MMR "rewards difference", and the category version "penalizes sameness". Both are in the same pipeline, and each is turned on and off by a parameter (param-gated) verified — ScoredTweetsRecommendationPipelineConfig.scala:580-601.

  • MMR parameter: TwhinDiversityRescoringParam :589-590
  • Category parameter: CategoryDiversityRescoringParam :593-594

When both are on, they apply on top of each other. The ScoreFeature that the category version reads as relevance is already the value MMR overwrote. The two adjustments are not independent but compose in series verified. The basis is the in-place overwrite by MMR described above.

The two adjustments appear to run after the top-K cut, but the execution position cannot be confirmed from the code inferred.

  • Both are placed in a stage named postSelectionFeatureHydration, so they appear to run after the top-K cut inferred. The only basis is the stage name and the fact that this stage is placed after resultSelectors (:574-577, including DropRequestedMaxResults).
  • However, RecommendationPipelineConfig.scala in product-mixer/core, the framework code vendored in the repo, defines only resultSelectors (:136) → postSelectionFilters (:142). There is no postSelectionFeatureHydration hook at all. That is, the execution position cannot be confirmed from the code verified (absence) — grep -r postSelectionFeatureHydration product-mixer/ → 0 hits

3. DPP — 2026, a separate service

The 2026 generation's DPP is computed by a separate service verified. The VMRanker scorer in home-mixer (X's service that serves the For You feed) calls this service over gRPC and overwrites the existing score with the response score verified — home-mixer/scorers/vm_ranker.rs:47-52 (Gen3 0bfc279).

DPP parameters are built only when at least one of theta and max_selected_rank is positive verified — vm_ranker.rs:112-120.

let dpp_params = if dpp_theta > 0.0 || dpp_max_selected_rank > 0 {
    Some(DppParams { theta: dpp_theta, max_selected_rank: dpp_max_selected_rank })
} else { None };

theta controls the trade-off between relevance and diversity, and max_selected_rank appears to be the length of the top part to which DPP is applied inferred. The basis is the names and DPP convention; the code has no explanation.

The DPP service itself has been in the repo's vm-ranker/ since the Gen4 release (2026-08-13) verified. The kernel matrix is built from candidate scores and embedding cosine similarity verified — vm-ranker/dpp.rs:94-133 (HEAD 862a123, 2026-10-17).

  • The kernel element is L_ij = exp(α·q_i) · exp(α·q_j) · cos(e_i, e_j), where q_i is the candidate score divided by the top score and α = θ / (2(1 − θ)) verified (same file).
  • Selection is a greedy DPP that updates the Cholesky decomposition one row at a time verified — dpp.rs:223.
  • The Gen4 release commit has the same kernel verified — vm-ranker/dpp.rs:94-124.
  • Up to Gen3 (0bfc279), the repo had only the client and the proto mapping, and xai_vm_ranker_proto was an external crate verified.

When the call fails, the DPP result silently disappears. If gRPC fails, it returns Err for every candidate, and the pipeline's update_all skips this Err without even logging it verified — candidate-pipeline/scorer.rs (default update_all implementation), vm_ranker.rs:33-38.

fn update_all(&self, candidates: &mut [C], scored: Vec<Result<C, String>>) {
    for (candidate, scored) in candidates.iter_mut().zip(scored) {
        if let Ok(scored) = scored { self.update(candidate, scored); }
    }
}

→ If VMRanker has an outage, a pure score-ordered feed goes out without diversity optimization, and nothing in the response indicates it. This is fail-open behavior. Observing this state requires a separate metric.

VMRanker as a whole can be turned off with the EnableVMRanker FeatureSwitch verified — vm_ranker.rs:18-20.

For topic requests, DPP is skipped by default (2026-10-14). The default of the new switch TopicDppEnabled is false verified — vm-ranker/scoring/mod.rs:85-87.

4. Dedup — in practice, this is the densest part

In both generations, dedup is split across several filters verified. The 2026 generation has the following three filters verified home-mixer/filters/:

  • drop_duplicates_filter
  • retweet_deduplication_filter
  • dedup_conversation_filter

The 2025 Scala generation has 6 dedup filters alone, and each filter's trigger condition is narrow verified.

Filter Rule Location
RetweetDeduplicationFilter First puts all non-retweets in the candidate pool into seen. Then removes a retweet if its own id or its original id is in seen :27-36
MediaIdDeduplicationFilter Targets only candidates with exactly 1 media item. Multi-media candidates are not targeted :26,33-35
ClipClusterDeduplicationFilter Applies only when there is 1 cluster. It counts the distinct values of a Map[Long,Long], so 4 images in the same cluster are also targeted :24-27,29
DuplicateConversationTweetsFilter After removing ancestors, keeps only one reply per root by maxBy(ScoreFeature). All candidates without a root (non-conversations) pass :33-40
QuoteDeduplicationFilter Removes the quoted original (not the quote post) :23-26, pipeline wiring :603,609
KeepTopKCandidatesPerCommunity Keeps 1 per community and limits total community candidates to 3 (MaxCandidatesPerCommunity = 1, MaxCommunityCandidates = 3) :14-15,30,32

The if (mediaIds.size == 1) condition in MediaIdDeduplicationFilter appears to be deliberate conservatism, because removing a post when two 4-image posts overlap by only one image would be excessive inferred. The code gives no reason. In addition, the file name is MediaDeduplicationFilter.scala but the object name is MediaIdDeduplicationFilter verified.

The direction of QuoteDeduplicationFilter is the opposite of intuition. Reading it as "quote dedup" suggests it would remove the quote post, but it actually removes the quoted original from the feed. This is presumably because the quote already shows the original inferred.

tweet-mixer, which handles generating candidates from accounts the viewer does not follow (OON, out-of-network), has a separate rule that keeps only 1 per author, for low-signal users only verified — HomeRecommendedTweetsRecommendationPipelineConfig.scala:364. Low-signal users are users with a small follow graph.

  • The code is DropDuplicateCandidates(duplicationKey = _.features.getOrElse(AuthorIdFeature, None)).

5. Learned slate decoder — 2026-10, training code only released

The page-level RL decoder whose training code X released in the 2026-10-14 commit puts a diversity penalty in both the slot-selection stage and the training loss verified. The serving switch is off by default verified.

The released decoder is page_rl, a page-level RL decoder for immersive surfaces verified — phoenix/xrex/models/page_decoder.py. The decoder picks slots one at a time, and at each step adds the two features below to the logit as negatively weighted features verified — page_decoder.py:85-119, 233-247.

  • "Whether the author is the same as one already picked"
  • "How many leading levels of the SID overlap". SID (semantic ID) is an ID that represents an item as a multi-level hierarchical code.

The training loss also includes a penalty (weight 0.5) for placing the same author or similar SIDs consecutively verified — page_decoder.py:569-578.

  • Whereas approaches 1–3 above apply diversity as rules after the score is set, this approach learns the size of the diversity penalty together with the dwell reward. It is in the same direction as Netflix GenPage (single-Transformer page generation) moving row selection into the generative distribution inferred. The only basis is the structural similarity that both companies place diversity inside a generative model rather than in a separate layer.
  • The serving switch serve_page_decoder is False by default, and home-mixer has no code that uses this decoder verified. The deployment scope is unknown.
  • For details, see the section on the 2026-10-14 commit in x.md. These notes number X commits after the Gen4 release in sequence, and this commit is Gen4+41.

↑ Contents

Case: Meta — nothing published for the main feeds

Although Meta publishes ranking documents steadily, it has never written about diversity and dedup at the algorithm level inferred. This contrasts with X, where the form of the decay function, the MMR formula, and the trigger conditions of the 6 dedup filters can be read line by line. This is not a gap in our survey but a finding we made.

  • The documents Meta keeps publishing are 30 per-surface AI system cards, DSA risk assessment documents, and engineering blogs.
    • An AI system card is a document that explains the ranking approach for each surface, and DSA is the EU Digital Services Act.
  • These documents disclosed prediction head names, individual feature sentences, per-stage candidate counts, and even how weights are set.

The diversity statements available for Meta's main feeds are all listed below.

Surface All published sentences Grade and source
Facebook Feed Blog (2021) description of pass 2: "the contextual pass. Here, contextual features, such as content-type diversity rules, are added to help diversify Juan's News Feed." Card description: "tries to ensure that your Feed has a balanced mix of content types. That means, for example, you wouldn't see multiple video posts in a row" verified engineering.fb.com, 2021 · fb-feed card
Instagram Feed "The system also tries to ensure your feed has a balanced mix of content types." It is even less specific than the Facebook sentence verified ig-feed card
Instagram (Mosseri) "we try to avoid showing too many posts from the same person in a row, or too many suggested posts back to back" verified Instagram Ranking Explained, 2023
Instagram Explore "in case we would like to increase the diversity of results, we might shuffle items based on some business rules (e.g., 'Do not show items from the same authors in a sequence')". This is the only sentence on a Meta organic surface that gives a rule as an example. However, it says "in case we would like to", so whether it actually fires is unconfirmed verified Scaling the Instagram Explore recommendations system, 2023
Threads Not a single sentence. There is not even a statement at the level of "multiple video posts in a row" observed 2026-08-09 (body text of the ig-threads-feed card, 1 item)

For algorithm names such as MMR/DPP, decay functions, thresholds N, and dedup rules, we found no primary source for any of them (no primary source found) inferred.

  • The corpus we examined is the 6 primary sources in the table above, 15 Transparency Center system cards, and the body text of engineering.fb.com, ai.meta.com, and about.instagram.com (accessed 2026-08-09).
  • This result is not evidence that undisclosed material also lacks them.
  • Author diversity alone is an exception. Explore gave "same authors in a sequence" as an example (see the table above).
  • ⚠ The Instagram notification blog (2025) names "maximal marginal relevance (MMR)". However, it concerns notifications rather than feeds, so the scope of the absence claim above is limited to feed surfaces verified.

What can be known is only the position where diversity is applied. Diversity is applied in pass 2, a separate pass after pointwise scoring ends verified 2021. This is structurally the same position as X placing MMR and DPP in a post-selection stage inferred.

There is also a statement that listwise (looking at the whole list together) prediction and delivery frequency control exist verified ai.meta.com, 2023. However, their form is not public.

"pointwise and listwise predictions"

"personalized methodology for delivery frequency control to optimize for long-term user value"

However, Facebook also uses diversity as a ranking feature

On Facebook, the same diversity concept is both a re-ranking rule and a ranking input. A corresponding feature actually exists on the card verified fb-feed.

"Number of times you have seen posts with the same content type (e.g. video, photo, etc) as the current post in the past hour"

Within the scope this repository recorded, X's diversity on the home-mixer serving path is entirely post-hoc score manipulation (decay, MMR, DPP, dedup), and no ranker feature of the "how many times has the user recently seen the same type" family appears. However, we did not review X's full ranker feature list to confirm this, so it is inferred. Confirming it would settle whether this contrast holds (see "Not Yet Confirmed" below).

The decoder in section 5, which learns a diversity penalty, is excluded from this contrast because its serving switch is off by default verified (section 5).

The only exception — the multiplicative penalty in Instagram notifications (2025)

The post on Instagram notification ranking is the most mechanical diversity disclosure in all of Meta. However, its subject is notifications, not feeds. This framework multiplies a notification candidate's base relevance score by a multiplier that cuts the score according to similarity to recently sent notifications verified (see the quote from the post below).

Score(c) = R(c) × D(c)
D(c) = ∏_{i=1..m} (1 - w_i · p_i(c))
p_i(c) = max_{h ∈ H} sim_i(c, h)

Source: A New Ranking Framework for Better Notification Quality on Instagram, 2025-09-02

⚠ The three lines above are not a verbatim quote. In the original post, these formulas are rendered as LaTeX images (latex.php?latex=…), so they do not exist as body text. The notation above was transcribed from looking at those images observed 2026-08-09 (we fetched the post body and confirmed that every formula position is an image tag).

However, each component is directly supported by prose in the body rather than by the images verified same post:

  • They combine by multiplication: "the product of its base ranking score and a diversity demotion multiplier"
  • "R(c) represents the candidate's base relevance score"
  • "D(c) ∈ [0,1] is a penalty factor that reduces the score based on similarity to recently sent notifications"
  • "sim_i(·,·) is a predefined similarity function for dimension i"

→ Only the exact form of the product symbol and the max operator depends on the images; the rest (the multiplicative structure, the definitions of R and D, and the fact that the comparison target is recent send history) is confirmed by text inferred. The interpretation below is based on that text.

  • Symbol meanings:
    • R(c): base relevance
    • D(c) ∈ [0,1]: penalty
    • H: recent send history
    • w_i ∈ [0,1]: per-dimension strength
    • τ_i: similarity threshold
  • The baseline implementation defines p_i(c) this way: "equals 1 if the similarity exceeds a threshold τ_i and 0 otherwise". That is, it is a step function, not a continuous similarity.
  • There are 4 dimensions: content / author / notification type / product surface

Placed next to X's two forms, all three differ.

Comparison set Direction Combination
X 2025 MMR Candidates already selected in this request Rewards distance Addition
X 2025 category penalty Category counts in this request Penalty for sameness Addition
IG 2025 notifications Recent send history H (outside the request) Penalty for similarity Multiplication

Two points matter especially.

  • The comparison set differs. X's MMR compares candidates with each other within the slate, whereas Instagram notifications compare against what was already sent in the past. Notifications are not a slate but a stream sent one at a time along the time axis, so the comparison target has to be history inferred.
  • Multiplication makes it a veto. When w_i = 1 and the similarity exceeds the threshold, D(c) = 0 and the whole score becomes 0. With X's additive form, relevance can win however large the penalty is, and the category version sets a floor with max(…, 0.00001) verified. The property that a multiplicative penalty works as a hard veto is of the same nature as the Instagram 2020 value model → multi-task-ranking.md.

Retrieval-stage diversity — Instagram's main effort may be here

Instagram's diversity may rely mainly on mixing in advance at the candidate generation stage rather than on re-arranging after ranking inferred. The post-ranking wording stays at the level of "too many", whereas on the retrieval side even method names and parameter values appear.

The retrieval DSL (the language for writing candidate generation queries) has a one-line diversify_by(seed_id, method=round_robin) verified — Designing a Constrained Exploration System, 2020. This is round-robin per seed account, and max_media_per_account=10 in the same query is of the same kind.

X also places a round-robin weave in tweet-mixer (mixing source and signal buckets in turn) and a dedup of 1 post per author for low-signal users at the retrieval stage, so the stage of application itself is shared inferred → candidate-allocation.md.

Debunk — "Instagram blocks 3 consecutive posts from the same account"

We could not find a Meta primary source for this widely repeated story inferred. The corpus checked is the same as in the Meta case section (15 cards and 3 Meta blog families, read 2026-08-09). The one thing we confirmed directly is that Mosseri's actual sentence contains no number observed 2026-08-09 (1 post body, quoted below).

Mosseri's actual sentence is below verified — Instagram Ranking Explained, 2023-05-31.

"we try to avoid showing too many posts from the same person in a row, or too many suggested posts back to back"

  • He said "too many", so there is no threshold. He said "try to avoid", so it is not a hard constraint either.
  • We could not find the number "3" in Meta documents inferred (same corpus).
  • The same sentence states two different constraints. One is consecutive posts from the same author; the other is consecutive suggested (unconnected) posts. The latter has no counterpart statement for Facebook.
  • Ironically, X is the one with a constant "3" actually in code verified. MaxCandidatesPerCommunity = 1 and MaxCommunityCandidates = 3 are those values verified (table in section 4). For author diversity, X's function form ((1-floor)·decay^n + floor) is also readable, and the coefficient values are decay 0.5 and floor 0.25 in the Gen4 (47c1bcd) mirror verified (section 1).
  • This misunderstanding has the same shape as X's "in-network 50:50" (the story that posts from followed and unfollowed accounts are mixed half and half) inferred. One qualitative sentence hardens into a specific constant as it circulates inferred. The section that covers that misunderstanding is in candidate-allocation.md.

↑ Contents

Case: Netflix — the unit of diversity is the page, not the list

As of TMIS 2015, Netflix's diversity sits in the row selection stage, not in a re-ranking layer verified. Because the home is a 2-dimensional page of rows × columns rather than a single stream, the position where diversity is applied also differs from X and Meta. The primary source for the fifth approach, calibration, is also on the Netflix side, but there is no production deployment claim inferred.

When choosing about 40 rows from tens of thousands of candidate rows per member, it "optimizes for relevance and diversity" verified TMIS 2015.

  • It dropped templates in 2015 and allows "a home with no BYW rows at all, or a home that is half BYW." BYW is a Because You Watched row.
  • Because templates were dropped, diversity is a page composition problem, not a problem of manipulating item order.
  • If X's MMR and DPP deal with "how to rearrange a sorted list," Netflix deals with "which rows of different perspectives to place side by side."

The primary source for the fifth approach, calibration, is Steck's paper. Calibrated Recommendations (RecSys 2018) does greedy re-ranking with a KL-divergence penalty so that if a user watched 70% romance and 30% action, the recommendation list keeps that ratio. The form is greedy re-ranking like MMR, but the goal is "match the history distribution," not "make items differ from each other." Optimizing only for accuracy lets the majority taste (action) monopolize the list. Calibration is the device that prevents that monopoly (crowding-out).

  • ⚠ There is no production deployment claim. The paper proposes a methodology. We could not find a sentence saying "we deployed calibration" in any Netflix blog post or talk inferred. The corpus checked is all tags of netflixtechblog and the research.netflix.com publication list (read 2026-08-09). Do not write "Netflix uses calibrated recommendations"; "a Netflix researcher proposed it" is as far as is safe.
  • There is still a reason to keep it in this note. Decay, MMR, DPP, and dedup all belong to the "penalize sameness" family, while calibration alone follows a different criterion: distribution matching. So it makes us ask first, "what is this diversity aiming at?" when looking at a diversity layer.

Dedup may point in the opposite direction. X removes duplicates with 6 dedup filters. Netflix home, meanwhile, appears to allow the same title in several rows.

  • Each row has a different recommendation reason, such as genre, BYW, or Trending, and once artwork personalization (full rollout in 2017 verified) is layered on, a duplicate impression of the same title works as "a retry with a different explanation" inferred.
  • We have not found a primary source for the cross-row duplication rule, and have not yet observed it directly.
  • If confirmed, it becomes a case where the premise of item 4 in the top list, "dedup is hygiene," is overturned depending on surface structure.

Artwork is a separate lever that moves perceived diversity. Even for the same title, a different image is picked per member with a bandit (online learning that adjusts choices by watching responses), and this approach was fully rolled out in 2017 verified — blog post: "we've rolled it out to everyone!"

Even with the same item set, the visual diversity of the screen differs. It is a layer with no counterpart in the X or Meta literature.

Details are in netflix.md.

↑ Contents

What generalizes from this case

  • Diversity overwrites the ranking score. X overwrites the score field as-is in both the 2025 MMR and the 2026 VMRanker. When you see a "ranker score" in a log, check which stage the value comes from. This is why X 2026 keeps weighted_score and score as separate fields verified ranking_scorer.rs:277-281.
  • Put a floor on decay. Make it a penalty rather than a cap, so that popular authors do not disappear completely.
  • Expensive diversity (MMR/DPP) is applied to the already narrowed list, not the whole candidate pool. In both X 2025 and 2026 it is placed in the post-selection stage inferred (for 2025 the hook is not in the vendored core, so we could not confirm where it runs).
  • Diversity is applied toward the back of the list, not the front. X 2025 MMR adds a constant to the first (1-diversityRatio)×n items, effectively preserving pure relevance order. The distance reward is given only after that. The top few follow accuracy and those below follow diversity, and this division is explicit.
  • The diversity layer is fail-open. The feed goes out without this layer, so if it stops silently, nobody notices. Decay runs inside the same process and does not stop, while DPP is a remote call and does stop. This asymmetry explains why decay is kept inferred.
  • Keep dedup rules narrow. X repeatedly uses the condition "only when exactly 1". It appears to have judged that over-removal costs more than under-removal inferred.
  • What is not published is also data. Meta publishes even how it sets prediction heads, candidate counts, and weights, yet stays consistently silent only on diversity and dedup. This may be because diversity rules amount to "what to show less," which easily becomes a target of policy disputes inferred. The only evidence is that the direction matches the pattern of demotion (impression demotion) documents being heavily deleted in 2025 → facebook.md.
  • Whether a penalty is multiplicative or additive decides whether it is a veto. The multiplication in IG notifications sets the score to 0 when items are similar. The additive form in X MMR and categories leaves room for relevance to win. The same name "diversity penalty" points to opposite strengths.
  • When reading diversity logic, first ask what the comparison reference set is. Check first whether it compares within the slate, as X MMR does, or against past impression and send history, as IG notifications do. Even with the same max-similarity formula, this choice makes it a completely different approach.
  • There is no rule that diversity must live only in post-hoc re-ranking. Facebook uses "the number of same-content-type impressions in the last 1 hour" as a ranking feature, and Instagram states round-robin explicitly in the retrieval DSL. Looking only for post-hoc layers misses half.
  • Surface structure decides the unit of diversity. In a single stream (X, Meta), adjacency within the list is the problem, so decay and MMR are the answer. In a 2-dimensional page (Netflix), row composition is the problem, so diversity moves into the row selection algorithm. The same word "diversity" manipulates different objects.
  • "Penalize sameness" and "match the distribution" are different goals. Decay, MMR, and DPP penalize adjacent sameness, while calibration fits the genre distribution of the whole list to the history. The former lets the top-scoring taste monopolize the list as long as the items differ. The latter prevents that monopoly (crowding-out) itself.
  • Publishing the formula and deploying are separate. Netflix calibration is one of the few diversity algorithms whose full formula is public via a RecSys paper, yet there is no deployment claim. Conversely, Meta's deployment is certain (pass 2) but there is no formula. "Level of disclosure" and "certainty of deployment" are independent criteria.

↑ Contents

Who uses this

X has all four diversity approaches readable as source code verified. Threads, meanwhile, has no primary source at all for diversity and dedup observed 2026-08-09.

  • X: All four approaches are readable as source code. → x.md verified
    • 2025: MMR, category penalty, 6 dedup filters
    • 2026: author decay, DPP, 3 dedup filters. Since 2026-10 there is also training code for a trained slate decoder.
  • Facebook: The pass 2 context pass has a content-type diversity rule. The algorithm is undisclosed, and the only concrete rule is the single line "multiple video posts in a row". Instead, the same concept also exists as a ranking feature. → facebook.md verified
  • Instagram: The feed has only wording at the level of "too many … in a row". Retrieval has diversify_by(round_robin). Only for notifications did it publish the full multiplicative penalty formula. → instagram.md verified
  • Threads: There is no primary source at all for diversity and dedup. → threads.md observed 2026-08-09 (body of the ig-threads-feed card and 2 Threads engineering blog posts)
  • Netflix: Diversity is in the row selection stage (since 2015). It published the calibration formula (2018, deployment unconfirmed). It has a separate lever, artwork personalization, and dedup may in fact be looser. → netflix.md verified
  • Other services: Not yet investigated. This is an open question.

↑ Contents

Not yet confirmed

We have not yet answered the questions below.

  • Does the X ranker input have a feature in the family of "recent impressions of the same content type"? To write that there is none, the whole repo must be checked. The contrast with Facebook depends on this check.
  • The form of Meta's pass 2 diversity rule. We do not even know whether it is a hard slot constraint or a score penalty → facebook.md open question 2.
  • Does the Instagram notification framework also apply to the feed? The post limits its wording to the notification surface.
  • Does a diversity or dedup layer actually exist on Threads? We cannot tell whether the absence means "not published" or "does not exist."
  • The form of Meta's listwise prediction and delivery frequency control. Only existence statements exist, with no mechanical wording.
  • Whether Netflix calibration is deployed. There is only the paper and no deployment claim.
  • Netflix's rule for allowing duplicates across rows. There is no primary source or direct observation yet.
  • Where does diversity go under a GenPage regime? If the explicit point of applying diversity, row selection, disappears, diversity dissolves implicitly into the learned generative distribution. There is no statement on this → netflix.md.

↑ Contents

Sources

Public source code

  • xai-org/x-algorithm — 2026, public source code (Apache 2.0). home-mixer/scorers/, home-mixer/filters/, candidate-pipeline/. The topic request paragraph in section 5 and the DPP section is as of commit 17c96bf (2026-10-14). The home-mixer line-number quotes in sections 1 and 3 are as of 0bfc279, the Gen4 defaults as of 47c1bcd, and the DPP kernel as of 862a123. Other line-number quotes without a sha are as of the time of writing (2026-08).
  • twitter/the-algorithm — commit c54bec0 of 2025-09-03, public source code. home-mixer/.

Meta blog posts

Meta Transparency Center (primary documents for regulatory compliance)

Netflix

↑ Contents