"Recency boost" is the single most repeated piece of X algorithm advice
on the platform itself. It survived the 2023 algorithm release, which
mostly killed the heuristic-weighted recency curve the 2020 era was
built on. It survived the 2026 rewrite, which removed the recency
multiplier from home-mixer/scorers/weighted_scorer.rs
entirely. What stayed is a recency window, not a recency multiplier,
and the distinction reshapes every cadence playbook creators rely on.
Posts are either in the window or out of it, with separate retrieval
mechanics for each side. This article walks the Thunder retention
layer, the three-layer impression-bloom architecture, the tweet-mixer
age cutoff, and the cadence playbook that respects both the 48-hour
reality and the diversity scorer's per-author caps. Companion to
A1
and A7
on cadence-and-diversity.
The recency-boost myth and where it came from
The 2020 Twitter ranker, before the heavy ML rewrite, weighted recency explicitly in the final score. A post one hour old scored higher than a post three hours old, all else equal, because the ranker multiplied candidate scores by a decay function over time. That mechanic produced the "post at the right time" advice that every Twitter growth resource through 2022 internalised: time of day matters, post when your audience is online, fresh content has a built-in scoring edge.
The 2023 release softened the decay considerably and folded most of the
recency signal into the ranker's learned representations. The 2026
release removes the recency multiplier from the weighted scorer
entirely. There is no RECENCY_WEIGHT constant. There is no decay
function multiplying candidate scores by age. The Phoenix transformer
in phoenix/recsys_model.py conditions every
prediction on the viewer's history sequence, but it does not have a
"this post is fresh" feature in its inputs in the public source.
What it has instead is a binary window. Inside the window, posts are in the in-network candidate pool. Outside, they are removed from that pool entirely and can only re-surface via the out-of-network retrieval lane. The window is implemented as a retention TTL in the Thunder service, not as a scoring adjustment in Phoenix.
Thunder's 48-hour window
thunder/ is the post-store service that maintains
the in-network candidate pool. Per-user in-memory stores hold three
post categories (originals, replies and reposts, video posts) with an
age-based trim. The default retention window, per
thunder/post_store.rs, is two days. After that,
posts fall out of Thunder's stores and out of the in-network candidate
pool for any subsequent feed request.
Practical implication: a post you ship today is eligible to surface in
your followers' feeds for approximately 48 hours via the in-network
retrieval path (home-mixer/sources/thunder_source.rs).
After 48 hours, the in-network path does not see it. The post can still
appear via the out-of-network retrieval path (the three Phoenix
retrieval sources walked in A3),
but only if its embedding similarity to the viewer's history sequence
clears the OON top-K threshold.
The asymmetry matters. In-network posts surface to followers who already have a relationship with the creator. OON posts surface to unfollowed viewers based purely on embedding similarity. A post that performed well in the 48-hour window with its follower audience is not guaranteed to perform well in the OON lane after the window closes. The followers' history sequences include the creator's many prior posts; OON viewers' history sequences do not. The two retrieval lanes have categorically different evaluation criteria.
Source: thunder/post_store.rs + home-mixer/sources/
| Stage | Time after publish | Retrieval lane | Notes |
|---|---|---|---|
| Publish documented | 0 | in-network (thunder_source.rs) | ingested by Thunder, joined to per-user in-memory store |
| Active window documented | 0 to ~48h | in-network primarily, OON secondarily | highest impression velocity, dominant retrieval lane is in-network |
| Late window inferred | ~24 to 48h | in-network declining, OON ramping | as Thunder's per-user trim begins, OON share of impressions rises |
| Post-window documented | beyond 48h | OON only | removed from Thunder; only Phoenix retrieval can surface |
| Long-tail documented | weeks to months | OON only, gated by MAX_POST_AGE | tweet_mixer_source.rs applies its own age cutoff to OON candidates |
Per-author caps inside the window
Even inside the 48-hour window, Thunder applies per-author caps to the
number of posts retained in each user's in-memory store. The source
code references three caps: MAX_ORIGINAL_POSTS_PER_AUTHOR,
MAX_REPLY_POSTS_PER_AUTHOR, MAX_VIDEO_POSTS_PER_AUTHOR. Numeric
values are not in the public source. The structural property is that
each viewer's Thunder store holds at most some bounded number of recent
posts from any one author. Past that boundary, even within the 48-hour
window, the oldest posts from that author for that viewer fall out
first.
The interaction with posting cadence is direct. A creator shipping ten posts in a 24-hour window crosses the per-author cap quickly, and the viewer's in-memory store only retains the most recent K of them. The earlier posts in that ten-post burst are evicted from the viewer's Thunder store, even though they are nominally inside the recency window.
For a follower-side intuition: the experience of "I follow this person but I only see their posts sometimes" maps onto a combination of per-author caps plus the diversity scorer (A7 walks the decay in detail). The creator is not invisible; their posts are bounded by how many of them can be in the candidate pool at any time, and only some of those bounded candidates clear the diversity decay during final ranking.
The three-layer impression bloom
Once a post is served to a viewer, the platform records that serving in an impression-bloom filter to avoid re-serving the same post in the same session. The 2026 source has three such filters:
Source: home-mixer/filters/
| Filter | What it tracks | Stage |
|---|---|---|
| previously_seen_posts_filter.rs documented | posts the viewer has already seen in recent sessions | pre-scoring |
| previously_served_posts_filter.rs documented | posts that have been served to the viewer (regardless of whether they were viewed) | pre-scoring |
| previously_seen_backup filter inferred | redundant tracking layer (presence inferred from source-inventory references) | pre-scoring |
The three-layer approach makes serving the same post twice unlikely even if one layer misses. For a creator, the practical implication is simple: each follower sees each of your posts at most a small number of times. After the bloom filter triggers, the post is removed from that viewer's candidate pool for subsequent requests.
Combined with the 48-hour Thunder window, this gives each post a finite total impression budget per viewer. The post is eligible for at most 48 hours, during which the viewer makes some bounded number of feed requests, of which the post is served at most a small handful of times. That bound is the structural ceiling on how much reach a single post can earn from any one follower.
MAX_POST_AGE in tweet_mixer
home-mixer/sources/tweet_mixer_source.rs applies
an additional MAX_POST_AGE cutoff on candidates flowing through its
auxiliary mixing pool. The cutoff is longer than Thunder's 48-hour
window but still bounded. Posts older than MAX_POST_AGE are excluded
from this source entirely. The specific value is not in the public
release; community observation of the platform's behaviour suggests
the order of magnitude is days to a small number of weeks, not months,
but this is widely-believed-not-documented territory.
The cutoff is the secondary age boundary creators occasionally
encounter as "evergreen content that suddenly stops surfacing." A post
old enough to have fallen out of Thunder is still potentially
retrievable via the OON Phoenix lane and via the tweet-mixer source,
but only until MAX_POST_AGE. Past that, the post is effectively
ineligible for any in-platform recommendation surface, regardless of
how well it performs on similarity to a viewer's history. Direct
profile visits and pinned-post slots remain, but those are not feed
retrieval; they are deterministic surfaces tied to specific viewer
actions.
A subtle implication: posts on X have a categorically shorter usable life than posts on LinkedIn or YouTube, where retrieval is not gated by a hard age cutoff in the same way. Creators porting evergreen-style content strategies from those platforms run into this boundary frequently. The fix is not to force evergreen on X; the fix is to recognise the platform's recommendation architecture is built for window-bounded retrieval and to optimise inside that frame.
A day-by-day walkthrough for a single post
To make the architecture less abstract, here is what happens to one post over its lifecycle. Assume a creator with 8,000 followers ships a post at hour zero. The numbers below are illustrative; specific values depend on audience composition and per-account history.
Hours 0 to 6. Thunder ingests the post and joins it to per-user in-memory stores across the follower base. The post becomes eligible for in-network candidate selection on every feed request from any follower. Phoenix scores it against each viewer's history sequence. The first wave of impressions arrives, primarily from followers who open the app in this window. Some posts in this wave fire the dwell heads, the favorite head, occasionally the reply or quote head. The predicted-action mix updates the per-creator history pattern for those followers.
Hours 6 to 24. The in-network impression rate continues but plateaus. Followers who already saw the post are filtered out by the three-layer impression bloom on subsequent feed requests. The per-author cap inside Thunder begins to bind: as the creator ships any additional posts during this period, the new posts enter the per-user stores and push the oldest posts toward eviction. The original post may already be the second or third in any given follower's per-author store, depending on the creator's recent cadence.
Hours 24 to 48. Thunder's per-user trim accelerates. Some followers' stores no longer contain the original post at all because newer posts from the same author have displaced it. The OON retrieval lane begins to carry a larger share of the post's impressions: viewers who do follow the creator but whose Thunder store has rotated out the post encounter it (if at all) via OON. The post's surviving impressions in this window come increasingly from OON-similarity matching rather than follow-graph membership.
Hours 48 onward. Thunder evicts the post entirely. The in-network
candidate pool no longer sees it. The post is now exclusively in the
OON retrieval lane. The tweet-mixer source's MAX_POST_AGE cutoff is
the next horizon; until that cutoff, the post can still be retrieved
via OON if its embedding similarity to a specific viewer's history
embedding is high enough to survive top-K. After MAX_POST_AGE, the
post is removed from tweet-mixer too, and only Phoenix's general OON
retrieval remains, increasingly constrained.
The aggregate impression curve over the full lifecycle is heavily front-loaded. Most of a post's total impressions arrive within the first 24 hours, with a long thin tail through 48 hours and a sparse re-surfacing pattern thereafter for embedding-distinct posts only.
The OON escape hatch
The one path by which an old post can still surface is the
out-of-network Phoenix retrieval lane covered in
A3.
Posts that score high enough on retrieval similarity to a specific
viewer's history embedding can be retrieved through this lane even
after Thunder has evicted them, subject to the MAX_POST_AGE cutoff
from tweet-mixer.
This is the structural reason a strong-voice post can occasionally "go viral months later" while a generic engagement post cannot. The strong-voice post sits in a sparse region of the embedding space where local competition is low, so its retrieval similarity to matched viewers' history embeddings stays high over time. The generic post sits in the dense centre of the embedding space, where local competition is intense, so even if its absolute embedding similarity to some viewer is moderate, the top-K survival rate is near zero.
The OON escape hatch is the only path by which evergreen value compounds for a creator on the platform. It is gated entirely by embedding distinctiveness, not by any recency, frequency, or engagement signal.
The cadence playbook that survives both windows and decay
Posting cadence on X is constrained by two distinct mechanisms running in parallel. The Thunder window plus per-author caps bound how many posts from a creator can be in any viewer's candidate pool at one time. The diversity-scorer decay (walked in A7) multiplies repeated-author scores by an exponential decay during final ranking. Together they impose a structural ceiling on what high-volume posting can earn.
Source: illustrative simulation
The chart sketches the qualitative shape. The volume-first curve rises and then flattens or declines because per-author caps and diversity decay bound additional posts' marginal impression delivery. The voice-first curve continues to rise modestly because per-post score quality remains high even at lower volume, and the per-post survival rate through the diversity layer stays above the decay floor.
The operational rule that drops out of the architecture: cadence
optimisation past three to five high-quality posts per day stops
producing meaningful additional impression delivery. The per-author
cap inside the 48-hour window holds at some bounded number; the
diversity decay multiplies posts at rank N by decay^N; the
impression-bloom filters cap re-serves. The net effect is a saturation
curve, not a linear one. The economic argument for shipping more is
weaker than the economic argument for making each post embedding-
distinct and dwell-firing.
What to do with this
Three operational moves drop out cleanly.
Treat the 48-hour window as the binary it is. Posts inside the window compete for in-network slot share; posts outside the window compete on OON retrieval similarity alone. Both lanes are valuable, but they reward different writing properties. In-network rewards voice-consistent posts in the historical pattern; OON rewards embedding-distinctive posts that survive the dot product.
Build for the OON escape hatch. The strongest investment a creator can make in evergreen reach is making each post embedding-distinct enough to survive in OON after Thunder's window closes. That property is unrelated to engagement counts inside the 48-hour window; it is a function of the post's distance from the broad-internet centroid covered in A8.
Stop measuring cadence in absolute posts-per-day. Measure it in "posts that fired the dwell heads in your follower audience." Three of those per day compounds. Twelve generic posts per day saturate the per-author caps and the diversity decay and contribute less than three of those high-quality posts.
The recency model in 2026 X is a window, not a multiplier. The cadence playbook that respects the window respects the diversity decay simultaneously. Both lead to the same place: fewer, more embedding-distinct posts, anchored to the creator's voice cluster. That convergence is what the cornerstone of this series opened with. The slot-competition mechanics walked in A4 close the loop on what those posts are actually competing against when they reach the rendered feed.