Every time you open X, a machine reads your recent behavior, pulls about a thousand candidate posts, and predicts — for you specifically — how likely you are to like, reply, mute, or report each one. This is that machine, stage by stage, built from the code xAI open-sourced.
↓ the request path flows down
The For You request path, per the open-sourced repo: sources → filters → scoring → selection → visibility → feed.
Opening X fires one For You feed request. The Home Mixer (Rust) runs it through a pipeline: hydrate your context, pull candidates from three sources in parallel, filter, score, pick the top K, then run visibility filtering. A second blending pipeline wraps it all and interleaves the things the model doesn't rank — ads, Who to Follow, prompts. Then side effects: record what was served, refresh caches, log events.
2023 → 2026: hand-built ranking features gave way to one learned transformer. The repo is Apache 2.0 and updates ship roughly every 4 weeks.
The 2023 open source (twitter/the-algorithm) described three stages: candidate sourcing (~1,500 posts), ranking with a Light Ranker then a Heavy Ranker neural net, and heuristics & filters. The 2026 repo (xai-org/x-algorithm) keeps Home Mixer as the orchestrator but replaces the hand-built machinery: in xAI's words, they “eliminated every single hand-engineered feature and most heuristics from the system.” Four components do the work now: Home Mixer (orchestration, Rust), Thunder (in-memory in-network post store, Rust), Phoenix (the Grok-based transformer that scores, JAX/Python with a Rust serving layer), and the Candidate Pipeline framework (Rust) everything is composed from.
Scoring every post on X for every viewer is impossible, so the pipeline first narrows the universe. Three sources are queried in parallel, and their results are hydrated (text, media, author, labels, engagement counts) and de-duplicated. Roughly half of a typical feed comes from accounts you follow; roughly half is out-of-network discovery.
Simplified illustration · animated
The candidate funnel
Watch the day's firehose shrink to the set Phoenix actually scores.
posts published today500M
Thunder · accounts you follow—
Phoenix retrieval · out-of-network—
SimClusters · cluster picks—
after dedup + pre-scoring filters—
Press “Run the funnel”.
Two-tower retrieval: Phoenix embeds you and each post as vectors, then returns the posts nearest to you — that's how strangers' posts reach your feed.
Thunder holds recent posts in memory as they're published and returns those from accounts you follow (config allows up to ~1,200). Phoenix retrieval is the two-tower model: it embeds the viewer and each post as vectors and returns the nearest posts (up to ~1,000) — pure out-of-network discovery. SimClusters groups accounts and posts by who engages with what and mines the clusters for more. Candidates are then hydrated — text, media, author details, labels, engagement counts — and pre-scoring filters strip out duplicates across sources, posts older than 48 hours, your own posts, blocked/muted accounts and keywords, already-seen posts, and subscriber-only posts you can't access.
Phoenix reads your recent engagement history — the main input to the model — plus the post and its author, and predicts how likely you are to take each of ~19 actions on it: like, reply, repost, quote, share, click, dwell, follow the author… or mute, block, report it. The final score is a weighted sum: score = Σ (weight × P(action)).
Phoenix predicts your personal action probabilities; the weighted sum becomes the score; adjustments and a diversity rerank finish the order.
Simplified illustration · interactive toy
Scoring playground
Four sample posts. Toggle the engagements you'd take on each — the score recomputes from the real published weights and the feed re-ranks live. Probabilities are toy (a toggle = it happens); the weights are the ones in the repo config.
Your engagement level — scales every positive probability, like the real model does per viewer100%
Your toy For You feed — live ranking
Three scorer stages run in order: PhoenixScorer emits a probability per action; RankingScorer takes the weighted sum, then applies author diversity (each post after an author's first is multiplied by a decaying factor, down to a floor), an out-of-network discount (a factor below 1 for accounts you don't follow), and a new-author boost (under ~1,000 impressions, lifted toward slots ~15–16). VMRanker then calls a separate service that reorders with a determinantal point process over post embeddings — trading a little score for less similarity between neighbors, so your feed isn't five versions of the same post. Then TopKScoreSelector keeps the top K. The single most misunderstood line in the repo: weights scale your predicted probability of each action — driven substantially by your own behavior — not raw engagement counts. A report's weight being 468× a like's does not mean one report cancels 468 likes.
Two separate filter moments. Pre-scoring filters run before ranking and remove the obvious: duplicates, stale posts, your own posts, blocked or muted accounts, things you've already seen. Post-selection visibility filtering runs after the order is fixed and answers one of three things per post: allow, interstitial (shown behind a tap-through, e.g. adult or graphic media), or drop.
Visibility filtering is separate from ranking: labels plus your own blocks/mutes decide allow, interstitial, or drop.
Simplified illustration · interactive toy
Filter demo
Nine posts enter the pipeline. Step through and watch each one get kept or dropped — with the reason stamped on it.
Stage 0 of 4 · candidates queued
Labels are produced continuously, off the request path: classifiers on text and media (grox, media models), account models like agatha (blocks and reports relative to favorites) and bdsm (inauthentic behavior over time), user-cred-v2 (PageRank over the follow and engagement graph), and rule engines (scarecrow embedding botmaker). On the request path, the visibility rules read those labels plus your own blocks, mutes, follows, and settings. A post dropped post-selection takes its thread, quote, or repost ancestors down with it. And you can audit some of this yourself: the Under the Hood page in Settings lets you download a JSON of the labels applied to your account and posts.
Not all engagement is equal. The weights below come from the repo's published config (synced Sep 28, 2026) — plus 2023-era values and one community estimate, each badged. Two things jump out: conversation dwarfs everything, and negative signals are enormous — because they're rare, so they're weighted up to matter at all.
Simplified illustration · real config values
The weight chart
Bars use a square-root scale so small weights stay visible — the numbers are exact. Badges: verified = current repo config · historical = 2023 open source · estimated = community analysis.
Weights multiply your predicted probability of each action — not raw counts. A report's weight is 468× a like's, but that does not mean one report cancels 468 likes: the baseline chance you'd report is 1000×+ lower than liking. Weights also ship roughly every 4 weeks — re-check the repo before quoting them.
Simplified illustration
The north star: unregretted user-minutes
X's stated goal for all of this machinery is maximizing “unregretted user-minutes” — time spent on the app you don't regret afterwards. The weights are one expression of it: replies, deep reads, and follows are treated as signs of time well spent; mute, block, and report as signs it wasn't.
Takeaways
As a poster: write things people reply to. A reply is worth ~10 likes in today's config (and the author's own reply back was worth 150× a like in the 2023 config). Ask real questions; be worth arguing with politely.
As a reader: your mutes, blocks, and reports are the strongest levers you have — negative weights are huge. Use them and your feed reshapes fast.
The feed is a mirror: every weight multiplies your predicted behavior. Two people see different feeds because the model has learned different versions of them.
Freshness matters: posts older than 48 hours are filtered before scoring even starts.
New voices get a shot: authors under ~1,000 impressions are boosted toward the middle of the feed, not buried.
Everything on this page comes from one of three places — kept deliberately separate:
Verified
From xai-org/x-algorithm itself: the Phoenix scorer, the action list, the current weights in home-mixer/params/param.rs, the filter names, the visibility rules, the component layout. Quoted verbatim where it matters.
Historical
From twitter/the-algorithm (Mar–Apr 2023) and X Engineering restatements: the Light → Heavy Ranker era, the famous +75 / +13.5 / −369 weights. Directionally current, numerically stale — the config has moved on.
Estimated
Community analyses, e.g. bookmark ≈ 10× a like. Never in any public config. Treated as a guess, labeled as one.
Weights ship roughly every 4 weeks, and the repo's config defaults may not exactly match production. If you're quoting a number, re-check the source first: