Why does my reach swing so much post to post?

Because reach is the product of many independent variables, and several reset every time. Each post is retrieved for a different, partly-random set of feeds; competes against whatever else is live at that moment; is shown to viewers with different seen-histories and mutes; and rides early-engagement signals that compound. The released code has no per-post "consistency" — it scores each post fresh against a changing field. Variance isn't a glitch or a shadowban; it's the expected behavior of a system where the same post meets a different world each time.

You post two similar things; one gets 500 views, the next gets 50,000. The instinct is that something changed about you — a shadowban lifted, a penalty applied. Usually nothing about you changed. The released architecture explains the swing without any account-level switch.

Every post meets a different field

Reach is a chain of independent draws, and the code shows each link resetting per post:

variablewhy it changes every post
Who it's retrieved forPhoenix out-of-network retrieval surfaces your post to a different candidate audience each time.
What it competes againstIt's scored against whatever else is live in those feeds at that moment — a changing field.
Who's eligible to see itThe previously-seen and muted-keyword filters remove it for different viewers depending on their history and settings.
Early engagementThe scoring signals reward predicted engagement; a strong first hour compounds into more reach, a weak one doesn't.
CODE-CURRENT0bfc279verified 2026-06-12
Before scoring, Home Mixer removes: duplicates, posts that failed metadata hydration, posts older than a threshold, your own posts, repost duplicates, paywalled content you can't access, posts you've already seen or been served, posts containing your muted keywords, and posts from authors you've blocked or muted.
xai-org/x-algorithm — README.md, Filtering section (Pre-Scoring Filters table, lines 296–314)as of the May 15, 2026 release

The seen-filter alone creates variance

The previously-seen filter removes your post for anyone who already encountered it — using both client-sent seen IDs and a bloom filter. The set of "already saw it" viewers differs every time you post, so the eligible audience is never the same twice:

home-mixer/filters/previously_seen_posts_filter.rs · L7–L8@ 0bfc279
 7// Filter out previously seen posts using a Bloom Filter and
 8// the seen IDs sent in the request directly from the client
CODE-CURRENT0bfc279verified 2026-06-12
The PreviouslySeenPostsFilter removes candidates the viewer has already seen, using both the seen_ids sent by the client and bloom filters; matching posts are partitioned into 'removed'.
xai-org/x-algorithm — home-mixer/filters/previously_seen_posts_filter.rs, seen_ids + bloom-filter partition (L23-L30)as of the May 15, 2026 release

Out-of-network is where the big swings live

In-network reach (your followers via Thunder) is relatively stable — that audience changes slowly. The volatility comes from out-of-network discovery: whether Phoenix surfaces you to a large relevant audience this time, and whether you clear the handicap, is where a post either catches or doesn't. Two similar posts can land on opposite sides of that line.

CODE-CURRENT0bfc279verified 2026-06-12
Out-of-network candidates have their score multiplied by an OON_WEIGHT_FACTOR, with the code comment stating the intent: 'Prioritize in-network candidates over out-of-network candidates.' The factor's value is in the withheld params module.
xai-org/x-algorithm — home-mixer/scorers/oon_scorer.rs, intent comment (L7) and multiplier (L20\–L23)as of the May 15, 2026 release

What the code doesn't say

▲ What the code doesn't say

How much variance is "normal." The code explains the sources of swing but not a distribution — there's no published number for expected post-to-post variance. Distinguishing normal variance from a real penalty requires measuring your own baseline over many posts, which is exactly the kind of judgment no single post can support.

UNKNOWN0bfc279verified 2026-06-12
The numeric values of the current weights are not included in the open-source release: weighted_scorer.rs references a params module (e.g. p::FAVORITE_WEIGHT, p::REPLY_WEIGHT) whose values are not present anywhere in the published repository.
xai-org/x-algorithm (verified by direct inspection of the full repository tree at the pinned SHA) — home-mixer/scorers/weighted_scorer.rs references crate::params; no params definitions with weight values exist in the releaseabsence verified at the pinned SHA; values may be published in a future release

What to do with this

Judge reach on trend, not single posts. One quiet post is noise; a sustained shift against your own baseline is signal. This is precisely why xDoctor scores against your trailing distribution rather than absolute numbers — it's built to tell ordinary variance apart from a genuine change in how you're being treated, which no individual post can reveal.

← Reach problems