Do blocks and mutes hurt my ranking?
Yes — through three distinct mechanisms visible in the live code. The scoring formula includes the predicted probability that a viewer will block, mute, or report you, weighed against every post before anyone actually acts. The viewer's real block and mute lists — including muted keywords — are loaded as first-class ranking features. And whether you have blocked the viewer is checked per post. Blockability is not an aftermath of bad posts; it is an input to ranking them.
The intuition most people carry is that blocks hurt you after they happen — accumulate enough and something somewhere flags your account. The live code says something sharper: the system is predicting blocks before they happen, on every post, for every viewer, and scoring you on the prediction.
Mechanism one: predicted rejection is in the formula
The weighted scorer that combines all engagement predictions ends with four lines that deserve their own page — this one:
64 + Self::apply(s.not_interested_score, p::NOT_INTERESTED_WEIGHT) 65 + Self::apply(s.block_author_score, p::BLOCK_AUTHOR_WEIGHT) 66 + Self::apply(s.mute_author_score, p::MUTE_AUTHOR_WEIGHT) 67 + Self::apply(s.report_score, p::REPORT_WEIGHT);
block_author_score is Phoenix's estimate, per viewer, of the probability that
showing them your post ends with them blocking you. Same for mute and report. These predictions
are weighed into the score of every candidate post — which means a posting style that makes a
slice of every audience reach for the block button is paying a ranking tax on every impression,
even on the viewers who never block anyone.
The model explicitly predicts negative actions — not interested, block author, mute author, report — and these carry negative weights in the final score, pushing down content a user would likely dislike.
Mechanism two: the viewer's lists are ranking features
Alongside the predictions, the system loads each viewer's actual social-pruning state. This is the complete per-viewer feature struct from the same release:
7pub struct UserFeatures { 8 pub muted_keywords: Vec<String>, 9 pub blocked_user_ids: Vec<i64>, 10 pub muted_user_ids: Vec<i64>, 11 pub followed_user_ids: Vec<i64>, 12 pub subscribed_user_ids: Vec<i64>, 13 pub follower_count: Option<i64>, 14 }
Six fields define what the ranker knows about a viewer, and half of them are exclusion
machinery: who they've blocked, who they've muted, and — first in the struct — which words
they've muted. Muted keywords are a first-class ranking input: phrasing alone can remove you
from feeds, one viewer's mute list at a time, with no penalty, no flag, and no way to see it
from your analytics.
The per-viewer feature struct consumed by ranking contains six fields: muted_keywords, blocked_user_ids, muted_user_ids, followed_user_ids, subscribed_user_ids, and follower_count \— the viewer's muted keywords and block/mute lists are first-class ranking inputs.
Mechanism three: your blocks shape your reach too
The pipeline also checks the reverse direction — for every candidate post, whether its author has blocked the viewer:
45let author_blocks_viewer = blocked_by_user_ids.contains(&candidate.author_id); 46Ok(PostCandidate { 47 author_blocks_viewer: Some(author_blocks_viewer), 48 ..Default::default() 49})
Every block you hand out is a standing instruction about your own distribution, hydrated from
the social graph on every feed request. Blocks are not a one-way shield — they are edges in the
graph the ranker reads in both directions.
For every candidate post, the pipeline checks whether the author has blocked the viewer and hydrates an author_blocks_viewer flag from the social graph \— block relationships are read in both directions during ranking.
Signal by signal
| in the code | in plain english | where xDoctor surfaces it |
|---|---|---|
| block_author_score, mute_author_score | Your predicted blockability is scored on every post, before anyone acts. | Coach · Reputation pillars |
| report_score | Predicted report probability is in the same sum — content that skirts rules pays the tax even when never reported. | Checkup · Flagged Posts |
| muted_keywords | Word choice can mute you out of feeds invisibly. Your vocabulary is part of your distribution. | Checkup · Language signals |
| blocked_user_ids / muted_user_ids | Each accumulated block or mute permanently removes a feed your posts could have reached. | Coach · Account health |
What the code doesn't say
The magnitudes. BLOCK_AUTHOR_WEIGHT and its siblings resolve to the withheld
params module, so how hard a predicted block punishes a post relative to how much
a predicted like rewards it is not in the open. The mechanisms above are code-current fact; any
claimed exchange rate between blocks and likes is invention.
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.
What to do with this
Treat blockability as a metric, not a mystery. The formula already does: it estimates, for every post, how likely each viewer is to reject you — which is precisely the signal family xDoctor's reputation diagnostics estimate from your archive, so you can see the pattern the model sees before the predictions harden into actual blocks. The spam screen and policy classifiers are the dramatic enforcement stories — this page is the quiet tax that compounds daily.