- Sources read: 5
- Canon files updated: 2
- Radar entries: 3
Other changes reviewed today:
- In the same commit, X made neither dense parameters nor embeddings update if either one fails the grad-norm check.
- X's reply spam flow no longer overwrites the reply ranking score written to Manhattan with a value higher than the existing one.
- There are no new sources for Meta and Netflix. On arXiv, three papers passed the radar: AMBER, TransRetrieval and SWIM.
1Phoenix checkpoint saving now has a host memory cap too — X
Source xai-org/x-algorithm@45b48ba — GitHub commit, 2026-08-26T20:04:12Z (36 files, +873/−525), public source code. These notes number X commits after the Gen4 release in sequence, and this commit is Gen4+9.
- The commit message is a single line,
"Open-source X Recommendation Algorithm", as is the convention in this series of generations. So the actual content can only be read from the file diffs. - By size, it falls between Gen4+7 (+1,418) and +6 (+856).
- However, the breadth of subsystems touched is wide (6 areas: Phoenix training, Phoenix serving, VF, ads proto, grox, home-mixer).
- Phoenix is the Transformer that serves as the ranking model for X For You and predicts engagement probability for each candidate. There is also Phoenix retrieval, which finds candidates from accounts the user does not follow.
- VF (visibility-filtering) is the service that decides, for each post, whether it may be shown to this viewer.
- grox is a Grok-based nearline annotation pipeline.
- home-mixer is the service that receives For You and Following feed requests.
Background The Gen4 open-source release of the X For You timeline has been followed by commits every other day or every day since the 2026-08-13 headline release (47c1bcd, +363,246/−11,640). The previous commit, Gen4+8 (0d3cdd8), was a broad release that touched six subsystems side by side with the following changes:
- AES (abuse-enforcement-service)
generic_actionspassthrough - Major simplification of VMRanker (slate reordering service)
- Expanded block relationships in the Following pipeline
- Brazil account update
- Phoenix
copy_porthardening
Yesterday's and today's releases form a pair. This Gen4+9 commit (45b48ba, 2026-08-26, +873/−525, 36 files) has two characteristics:
- It extends to the save side the maturation of Phoenix serving and training infrastructure that Gen4+8 started tidying yesterday.
- Today it tidies, in turn, ranker training consistency, LLM verdict prompts and VF stability, which yesterday did not cover.
The six changes in this commit are independent of one another and do not form a single thread.
1-A. Host memory caps were introduced on both the save and restore sides of Phoenix checkpoints
Both the code that saves Phoenix checkpoints and the code that restores them explicitly introduced a cap on RSS (resident set size, actual host memory occupancy). This change follows the restore-side hardening in Gen4+7 (2026-08-24). At that time, the concurrent_gb throttle and node-lock were applied only to restore. Gen4+9 applies the same principle to saving, and restore gained one more streamed variant.
- The changed files are
phoenix/xrex/utils/checkpointing.py(+215/−6) on the save side andphoenix/python/training/xai-checkpointing/xai_checkpointing/load.py(+311/−88) on the restore side. - The save side gained a new handler that splits tensors into batches and performs D2H (device-to-host copy) and write verified —
phoenix/xrex/utils/checkpointing.py:88-181.- It is named
ThrottledD2HArrayHandler. It inherits Orbax'socp.type_handlers.ArrayHandlerand overridesserialize(values, infos, args). - It iterates over the tensor list, accumulating each tensor's
addressable_nbytes(the actual bytes of the shard the current process is responsible for), and flushes the batch when it exceeds theconcurrent_byteslimit. - It calls super().serialize() for each batch and waits with
future.result()for D2H and write to finish before moving to the next batch. - In other words, instead of staging all tensors at once and consuming pinned-host memory all at once, it stages the next batch only after the D2H and save of one batch have finished.
- It is named
- The throttle size is given as an argument of the save function. If it is not given, the same stock Orbax handler as before (stage everything) is used, so backward compatibility is kept verified — same file.
- The form of the argument is
save_checkpoint(..., save_concurrent_gb=<N>). - Depending on whether compression is used, multiple inheritance is split into
ThrottledD2HArrayHandler(compressed) andThrottledNoCompressionArrayHandler(non-compressed).
- The form of the argument is
- There is also a node-level flock. When the env is on, it prevents multiple processes on the same node from saving at the same time, the same pattern as on the restore side verified — same file.
- When the
XAI_SAVE_NODE_SERIALIZE=1env is on, it takesfcntl.LOCK_EXon/dev/shm/xai_save_node_lock(or/tmp/...if absent). - The env on the restore side is
XAI_RESTORE_NODE_SERIALIZE.
- When the
- The log records the leaves count and GiB per batch, and warns explicitly if max_leaf exceeds the budget ("that leaf still D2Hs in one shot") verified — same file.
- It is a device that tells the user there is room for tuning when the throttle size is smaller than a tensor.
"save node-serialize ACTIVE (flock per batch) lock=%s pid=%d num_batches=%d" —
phoenix/xrex/utils/checkpointing.py, 2026-08-26
Why it matters Host OOM caused by the D2H stage outside wait_until_finished, when multiple workers save checkpoints at the same time on the Muon+GB300 generation, was probably observed inferred. This change is fully symmetric to the logic by which Gen4+7 introduced hardening on the restore side. It can be read as the result of confirming by measurement that the old stock Orbax setting ("write-limiter default 96GB, D2H of everything") is actually insufficient for saving large models, after Gen4+6 formally included flagship Muon training in the export.
- The restore side gained a new streamed loader that puts only one batch of tensors into pinned-host memory at a time verified —
phoenix/python/training/xai-checkpointing/xai_checkpointing/load.py:365-528.- It is named
load_checkpoint_streamed. - The existing
load_checkpointfirst builthost_state(a pinned-host copy of all tensors) and then did read into shards batch by batch. - The streamed version keeps
device_state. For each batch it goes through: stage only that batch's tensors to pinned-host → read files → device_put to device → update device_state → release the batch's pinned-host. - In other words, at any point the upper bound of pinned-host usage equals the size of the current batch.
- It is named
- A reasonable window is chosen automatically even if the user does not set the window value verified — same file.
- If
window_gb=None(the default), it is set to_auto_window_bytes= min(max(max_leaf, total/16), 32GB). - In other words, the window is the larger of max_leaf and total/16, but does not exceed 32×10⁹ bytes verified —
load.py:365-372. - So the target is roughly 16 batches or fewer. If max_leaf is larger than 32×10⁹ bytes, the window can be smaller than max_leaf.
- If
- When a batch completes and the device_state references are replaced with new arrays, the list of old and new pairs is passed to the on_replaced callback verified — same file.
- The caller uses this list to delete old arrays immediately or to swap links in other data structures.
- If no callback is given, the full list is returned.
- There is a helper that handles in advance the aliased case, where the same array object is referenced twice verified — same file.
- The helper is
copy_aliased_arrays. From the second reference onward in the jax tree, it makes an actual copy withmay_alias=Falsedevice_put. - It is handled in advance so that aliased references do not lose the original when streamed load swaps in new arrays batch by batch.
- The helper is
- Larger tensors are processed first to secure window packing efficiency verified — same file.
- The sort code is
plan.sort(key=lambda item: item[3], reverse=True). - A tensor of max_leaf or more fills a batch by itself anyway, so such tensors are gathered at the front.
- The sort code is
- A staging hook for warm start was added. When restoring only params from a checkpoint and reinitializing opt_state, no copy of opt_state is made in pinned-host either.
- The hook is
Trainer.warm_start_staging_spec(phoenix/xrex/train/trainer.py:1160-1165). - Previously, device_put with the staging sharding for restore moved the entire state structure to pinned-host.
- Now
warm_purge(self.state)cuts out opt_state in advance, stages to pinned-host, and device_puts only the loaded part again. The original opt_state field is left as is. RecsysTrainer.warm_start_staging_specoverrides this in the subclass to support thekeep_emb_opt_state=Trueoption.- Why it matters: warm start restore has become much lighter. This suggests that the flow where flagship Muon training starts from pretrained params and restarts the optimizer fresh has become standard inferred.
- The hook is
What we learnedOther changes
- The existing checkpoint loader also extracted 5 helper functions to tidy inline logic. The streamed version reuses these helpers.
- The target is
load_checkpoint. - The helpers are
_build_read_plan,_pack_read_batches,_convert_domains,_open_tensorand_drain_read_futures. - Exception logging was unified to rank_logger. The separate
logger = logging.getLogger("checkpointing")instance was removed, converging on the single rank_logger channel.
- The target is
- Phoenix serving's admission controller can now reset to zero the service_time and pipeline_time EWMAs it maintains. The corresponding Prometheus gauges also go down to 0.
- Added are
admission.reset_estimatesandrequest_metrics.reset_admission_estimates. - Two regression tests were also added (
reset_estimates_clears_s_and_p,reset_admission_estimates_clears_gauges_and_p). - The diff gives no clue why it is needed, but it appears to be meant for resetting the EWMAs immediately after a hot-swap or a sharp change in traffic profile inferred. It points in the same direction as the
_glibc_malloc_trim()post-swap processing in Gen4+6.
- Added are
- The weight load completion log now records total bytes, elapsed time and GB/s together (a divide-by-zero guard is also included).
- It applies to the completion logs of the dense weights load and emb_table load in
copy_port_client. - The start log "downloading dense weights prefix=... futures=..." was deleted, because the completion log now carries the summary information and the start log is no longer needed.
- It applies to the completion logs of the dense weights load and emb_table load in
Canon update In services/x.md, expanded this section's title to "Phoenix checkpoint stack save/restore dual hardening — Gen4+7 (restore) → Gen4+9 (save, streamed restore, warm-start staging)". It also added four items: the save side, the streamed variant, warm_start_staging_spec and admission reset.
1-B. If either dense or embedding fails the grad-norm check, both updates are skipped
In Phoenix training code (trainer_recsys), if the grad-norm check fails for either dense or embedding, both are now kept as the originals. Previously, if dense passed and only emb failed, dense params were updated to new values while only emb was rolled back, and this asymmetric state could last for a few steps. Now params and the embedding table move in lock-step.
- The parameter update condition was unified across the two training loops (dense sync and async_no_deferred) verified —
phoenix/xrex/train/trainer_recsys.py:1331-1400.- The file change is
phoenix/xrex/train/trainer_recsys.py(+29/−19).
- The file change is
Previously the updates went in this order:
- Check the dense grad-norm with
valid_step = is_valid_step(gradients). - Update dense params:
jnp.where(valid_step, updated, original) - After
segment_sum, check the emb grad-norm withis_valid_step(emb_gradients). - Update the emb table:
sparse_update(..., valid_step=emb_valid_step) - Record
valid_step = valid_step & emb_valid_stepin the metric.
After the change, the updates go in this order:
- Check the dense grad-norm to get
valid_step. - First run segment_sum and the emb grad-norm check to get
emb_valid_step. - Compute
keep_step = valid_step & emb_valid_step. - Update dense params:
jnp.where(keep_step, updated, original) - Update the emb table:
sparse_update(..., valid_step=keep_step) - Record
valid_step = keep_stepin the metric.
- The async path (
update_async_deferred) was unified in the same way.pending=jnp.asarray(True)changed topending=keep_step. As a result, the asynchronous emb gradient update reflects this step's gate result, which decides whether it is actually applied at the next step.
- The async path also actually uses the grad-norm threshold now. Previously, the async deferred path was assumed to be incompatible with grad-norm gating.
- This threshold is
grad_norm_keep_threshold. Theassert self.grad_norm_keep_threshold is Nonein_create_async_emb_executableswas removed.
- This threshold is
Why it matters The dense grad and embedding grad probably spiked at different scales on the Muon+GB300 generation inferred. Lock-step gating blocks the effect of this divergence from the start. It is a consistency adjustment for reproducible training.
Canon update Added a valid_step unification subsection to the Phoenix training and index section of services/x.md.
1-C. The reply spam verdict prompt can now include follower count and bio, and the reply ranking score written to Manhattan can only go down
In the grox reply spam (reply_spam) flow, the change has two parts. The LM verdict context was expanded, and a monotone-only gate was added to the Manhattan write. Both changes touch the reliability of reply spam and ranking verdicts as well as serving stability.
- The user metadata fed to the LM verdict was expanded verified —
grox/core/lm/post.py(+18/−6).The file changed together with it is
grox/core/lm/thread.py(+25/−4).Previously
PostRenderer.render()emitted user metadata as the single lineMetadata: <name> @<handle>; now it splits it into three:User Handle: @<handle> [User Follower Count: <N>] # when include_follower_count=True User Name: "<name>" [User Bio: "<bio>"] # when include_bio=TrueThreadRenderer._render_threadgained a newinclude_follower_countargument.Every post in the thread gets the follower count, and bio goes only into post 0 (the original, the thread root).
The last post, the reply target (reply-under-eval), also gets the follower count.
A
# Reply Author Infoheader was added before the message, explicitly giving the LLM a context hint that "this information is about the author of the reply to be evaluated".
Why it matters Follower count was probably a strong signal for reply spam and low-quality verdicts to begin with. The grox reply_spam pipeline was already using this signal to filter out bulk spam through the follower threshold in task_filter.py. Now the LM verdict itself also refers to this figure directly.
Bio is strong evidence for detecting spam and bots (a bio may contain spam hints such as "link in profile", or reveal affiliation with political or commercial organizations and interests). So exposing the profile of the original post's author as well raises verdict reliability. However, bios of the other participants in the reply thread are not included, which keeps the context from growing too long, and only the profiles of the two authors, the original post and the reply-under-eval, are expanded.
- When writing the reply ranking score to Manhattan, the write is skipped if the new score is greater than the existing one verified —
grox/flows/reply_spam/task_write.py:113-138.- The change is +22 lines.
_publish_to_reply_ranking_manhattanfirst looks up the existing score withReplyRankingScoreStratoLoader.fetch_reply_ranking_score(post.id).- If the new score is greater than the existing one, it skips the write and increments
Metrics.counter("task.write_reply_ranking_manhattan.skipped.count", reason="higher_than_existing"); if it is lower, it writes as is. - In other words, a reply ranking score sent out on this channel only decreases over time and never increases.
Why it matters If a reply's first verdict is low, the reply keeps a low score, and the serving score is not updated even if a later verdict becomes more lenient. Conversely, a reply whose first verdict is high (lenient) is lowered if later verdicts become stricter. This matches the monotone safety direction of reply spam verdicts, that is, once a reply is caught as spam it keeps being treated as spam, and only reclassification from normal to spam is allowed; it also removes oscillation of the reply ranking score over time, so the ranking of the same reply does not go up and down in the UI and in A/B tests. inferred Label flapping was probably actually observed in reply spam and ranking observation.
Canon update Added two subsections, LM context expansion and Manhattan monotone write, to the reply_spam section of services/x.md.
1-D. VF removed the media fallback cache it kept against TES lookup failures
The 1M-entry LRU-based fallback cache that VF used when looking up media entities from TES (Tweet Entity Service, X's internal tweet metadata service) was deleted entirely. Two related env flags and the code that wired them in disappeared as well.
- The cache lived in
TesHydrator, in the filevisibility-filtering/hydration/tes_hydrator.rs(+4/−292). - The two related config envs were also removed from
visibility-filtering/config.rs(0+/20−).VF_MEDIA_FALLBACK_CACHE_SERVE_STALE_ENABLED,VF_MEDIA_FALLBACK_CACHE_POPULATE_ENABLED
- The code and arguments that wired in the cache were deleted together.
- The wiring code in
server_deps.rs(9 lines) - The arguments in
hydration/mod.rs(2 lines) - The
media_fallback_cache_modeparameter ofHydrationPipeline::new
- The wiring code in
The logic before deletion was as follows:
- VF looked up media entities from TES, and if TES failed and no media feature came out, it kept the result of a previously successful lookup in the cache. When a later lookup failed, it substituted the stale but valid media feature (
FallbackCacheMode::ServeStale). - There was also a mode that only filled the cache without using it for serving (
FallbackCacheMode::Shadow). - The cache size was 1,000,000 (
CACHE_CAPACITY = 1_000_000), and eviction was LRU. - A large part of the 292 deleted lines were two regression tests using the
MediaFailingAfterFirstClientmock.media_stale_recovery_respects_cache_mode,no_media_tweets_cache_default_entries_that_serve_stale
Why it matters This fallback cache was likely a safety net for the stabilization period after the early VF rewrite (the Gen4 headline release) inferred. If a failure occurred while the TES infrastructure was being rewritten, a candidate would be caught by fail-close filtering without media features; the cache mitigated that destructive result. Its removal now means the following three things:
- The VF rewrite can now be audited for consistency with the Gen4+7
reference_compareharness. - The failure rate of the TES media path has dropped, so the marginal utility of the fallback cache has shrunk.
- The direction is the same as the major simplification of VMRanker in Gen4+8: "removing the safety net once things have stabilized".
However, the fallback caches of other hydrators (such as gizmoduck) are kept, so the fallback_cache_mode env also remains.
Canon update Added a subsection on removing the media fallback cache to the VF section of services/x.md.
1-E. The canary workload no longer enters dark traffic mirroring
The canary workload is dropped from VF's dark traffic mirroring. It is also not mirrored when the workload name is not set.
- The function that decides whether to mirror was extended to take the workload as well verified.
- The target is the
should_enable(ordinal, max_ordinal)function invisibility-filtering/dark_traffic_setup.rs(+40/−17). It was extended toshould_mirror(workload, ordinal, max_ordinal). - Added rule: if
workload=None(envWORKLOAD_NAMEis unset), it fails closed and does not mirror. - Added rule: if
workload.ends_with("-canary"), it does not mirror. In other words, a canary workload never enters dark traffic mirroring. - Otherwise it decides by
ordinal < max_ordinalas before.
- The target is the
- Two new tests were also added (
canary_never_mirrors,missing_workload_name_fails_closed). - The log message was also generalized from
"disabled (ordinal >= max)"to"disabled (not a mirror host)".
Why it matters The dark_traffic that Gen4+4 created was migrated from shadow to staging in Gen4+6. This change prevents the incident where a canary workload is mirrored by mistake and canary issues contaminate the shadow verdict. The production and canary workloads appear to share the same name prefix inferred, so suffix matching alone is sufficient.
1-F. Three conversion heads for ad pixel fires and an ad creative impression history field were added
Three new ActionNames related to advertiser pixel fires were added to Phoenix's proto. A field was added to the serving request to carry the history of ad creatives previously shown to the user.
- Three new ActionNames were added to the proto verified. The changed file is
phoenix/python/common/xai-proto/proto/recsys.proto(+12).- 191
ADS_PIXEL_FIRE: a web conversion event where the conversion pixel an advertiser placed on its own site fires. - 192
ADS_LONG_DWELL_AND_PIXEL_FIRE: an event that combines a pixel fire and long dwell (staying a long time on the landing page) with AND. It counts as the AND ofLONG_DWELL_AFTER_CLICK(158) andADS_PIXEL_FIRE(191). - 193
P_LONG_DWELL_AND_PIXEL_FIRE: the prefixP_appears to mean "primary" or "predicted" inferred. In light of the naming convention observed in the expansion of 20 ads conversion heads in Gen4+6, it refers to the predicted target of the primary conversion label.
- 191
- In the same commit, the field
reconCosMilli = 13entered the proto-sideSlateContextverified — same file.- As this document shows, home-mixer's
SlateContextalso hadrecon_cos_milliuntil Gen4+8 yesterday. - On the home-mixer side,
recon_count_above: Option<u32>andrecon_gap_above: Option<u32>were added this time, which refined the slate context reconstruction calculation. - These two fields are not yet reflected in the proto (the proto has only
reconCosMilli). They are waiting for home-mixer's local wiring to be moved to the proto.
- As this document shows, home-mixer's
- A path was also introduced to pass the history of conversion assets (ad creatives) previously shown to the user to Phoenix serving verified — same file.
- The field name is
conv_asset_ids, and its full path isPredictNextActionsRequest.conv_asset_ids. - The new message
ConvAssetIdshas a three-array structure ofrepeated int64 impressed_time_ms / author_id / asset_id. - The purpose appears to be ad creative attribution: the history is meant to be referenced for conversion prediction when the same asset is reused across several advertisers or the user saw the same asset several times inferred.
- The field name is
Why it matters This follows Gen4+6's large expansion of the ads conversion prediction heads by 20. This time it added three heads that combine pixel fire and long dwell, and created a path to carry asset history in the serving request. The ads ranker training stack continues to expand toward conversion prediction.
Canon update Added a subsection to the ads conversion section of services/x.md covering the three new heads in Gen4+9 and the conv_asset_ids wiring.
1-G. The retrieval user tower can now give history tokens a dedicated segment id
In Phoenix's two-tower retrieval model (a model that embeds users and items separately), the user tower's history tokens can now be given a dedicated segment id. A config flag turns this behavior on and off, and it is off by default.
- The user tower's attention segment id can now be set to the history-token-specific
HISTORY_SEGMENT_IDinstead of zeros verified.- The file is
phoenix/xrex/models/recsys_two_tower_model.py(+12/−1). HISTORY_SEGMENT_IDis imported fromxrex.pallas.ranker_attention_utils.- The flag name is
use_history_segment_ids, defined asRecsysTwoTowerModelConfig.use_history_segment_ids: bool = False. It is off by default.
- The file is
- The new function
user_tower_segment_ids(batch, seq_len, use_history_segment_ids)fills the whole shape (B, T) withHISTORY_SEGMENT_IDwhen the flag is on. When it is off, it fills with zeros as before.- When on, the user history tokens are grouped into one segment.
- Related defaults were also added to the
xrecsys_two_tower.pyconfig.
Why it matters This prepares for stating segment boundaries inside the user history sequence when the pallas flash-attention varlen kernel cuts the attention scope with a segment mask. Previously everything was a single zeros segment, so the segment mask itself was meaningless. Now special tokens with a different segment id (for example, the user_features token) can be isolated from the history tokens so they do not attend to each other. The accuracy of varlen packing improves.
Canon update summary
- services/x.md: Added or expanded a subsection in the x.md section that corresponds to each subsection above. The specific locations are noted under "Canon update" at the end of each subsection.
- services/x.md: Added the open question items for Gen4+9.
Why it matters Within the flow of daily commits since Gen4+7 (2026-08-24), today's release is a standard maintenance release, balanced between medium size and a breadth of six subsystems. There is no notable policy direction change. Where yesterday's Gen4+8 touched the relationship filter, enforcement and the retrieval index side by side, today's Gen4+9 extends training infrastructure (checkpoint and gradient gating) to the storage side and then tidies up the LLM verdict prompt and serving stability.
2AMBER, one token per interaction event, is served on Facebook — Radar (Meta)
Source AMBER: An Event is Worth One Token — arXiv 2608.25546 — arXiv, submitted 2026-08-26, paper. All 15 authors are listed as "AI at Meta", which we confirmed in HTML v1. The affiliation notation is ∗Core contributors, †Correspondence, AI at Meta.
Background LLM-based recommendation re-expresses the "user interaction sequence" as tokens and performs autoregressive prediction. However, earlier approaches (text, semantic ID, a few categorical features) carried shallow information at each position. As a result, the query context weakened, and this fed back in as the context of the next position, so performance degradation accumulated with sequence length. This paper (AMBER) presents Event Tokenization, which compresses one interaction event into one Event Token.
What we learnedAMBER compresses one event into one Event Token and encodes billions of events per day on Facebook
- Event Tokenization compresses the "temporal snapshot" of one interaction event (user, item, context and outcome signals, all of them) into one compact Event Token verified.
- This Event Token has taken its place as a new input type for LLMs. It improved the "compute-quality Pareto frontier" on industry-scale offline ranking and retrieval benchmarks verified.
- The Event Token can also be transferred to non-LLM rankers as a feature (transferability), and showed a statistically significant improvement verified.
- It serves the encoding of billions of events per day on the Facebook surface verified. The HTML says
"supporting online encoding for billions of events per day".
Why notable A fourth production claim is added to the LLM-native ranking thread. The three earlier claims are as follows:
- Netflix GenRec: scoring
- Meta ConnectionMind: graph reasoning
- Taobao MetaStrategy: offline policy compiler
Meta AMBER follows these from the input tokenization angle. Rather than placing an LLM in the serving path, it takes an offline or nearline encoder approach, while leaving downstream uses wide open. It is unusual that it is served as online encoding on the Facebook surface and also transfers to non-LLM rankers. Read together with Meta's ConnectionMind (graph path reasoner), it is a signal that LLM-based recsys approaches have split into at least two tracks even within Meta.
Canon update Added an AMBER entry to the new this month section of radar.md.
Why it matters It shows the architecture spectrum of "where to place the LLM" widening. The GenRec thread split into four branches (Netflix's scoring function, Meta's graph path reasoner, Alibaba's offline policy compiler and Meta's input encoder), so serving location, role and compute budget diversified in different directions. However, online A/B figures are stated in neither the abstract nor the HTML. The Facebook production deployment is confirmed, but the ranking metric lift is not public.
3TransRetrieval scales Transformer ads retrieval and raises revenue — Radar (Alibaba)
Source TransRetrieval: Scaling Up Transformer-Based Retrieval for Industrial Recommendation — arXiv 2608.25528 — arXiv, submitted 2026-08-26, paper. Of the 10 authors, 6 are affiliated with Alibaba (Taobao & Tmall Group Beijing) and 4 with Renmin University. We confirmed the affiliations in HTML v1.
- The Alibaba authors are Yunfei Liu, Bin Liu, Ziru Xu, Han Zhu, Jian Xu and Bo Zheng, senior authors of the Alimama ads line.
- The Renmin University authors are Zhifei Zheng, Qiren Zhu, Hanbing Liu and Qi Qi.
Background Several companies have tried applying LLM scaling laws to retrieval in recommender systems (HSTU, Wukong, LLaTTE). However, because of feature heterogeneity, simply stacking Transformer layers yields diminishing returns. Different fields produce token norms of different scales, so attention is dominated by features with large norms and signals are not mixed evenly. This paper (TransRetrieval) presents an aggregator that suppresses the token-norm divergence among heterogeneous fields so that the Transformer can be scaled.
What we learnedScaling ads retrieval with a Transformer still raised revenue under the same latency constraint
- Weighted average aggregation is an aggregator that suppresses the token-norm divergence among heterogeneous fields so that the Transformer can be scaled verified.
- Target token compression cuts the computation per candidate by 85% verified.
- Position-style domain embedding unifies cross-domain data with minimal overhead verified.
- A one-month production A/B was run on Alibaba's display ads platform verified.
"lifts platform revenue by 2.53% under the same end-to-end latency constraint as the production baseline" — TransRetrieval HTML, 2026-08-26
- The exact figures are below, and P99 latency stays at ~40ms verified.
- revenue +2.53% (95% CI [2.22%, 2.70%], p<0.0001)
- RPM +1.28% (CI [1.14%, 1.56%], p<0.0001)
- Spread across 4 domains: Domain A +1.72%, B +2.51%, C +5.39%, D +0.87%
Why notable The scaling law thread gets its first claim from Alibaba and Alimama. Until now the thread body cited two companies as evidence, Meta (HSTU, Wukong, LLaTTE) and Netflix (FM), and the Alibaba ads line is added to them. Counting entries outside the thread in order of submission date, ByteDance TM20K (08-07) and Ant Densing Law (08-24) fall in between. It is notable above all as a claim that applies scaling to the retrieval stack, because most companies started with the rank stack.
There is a dispute between LLaTTE's "no scaling without semantic features" and HSTU's "scaling alone works". In this dispute, TransRetrieval offers a third answer: "scaling is possible if field heterogeneity is handled explicitly". And because revenue +2.53% came under the same latency constraint, it is a strong production claim.
Canon update Added a TransRetrieval entry to the new this month section of radar.md.
4SWIM scores re-ranked lists per session in the Kuaishou main feed — Radar (Kuaishou)
Source SWIM: Step-Wise Integrated Measure for Session-supervised List Evaluation in Generative Re-ranking — arXiv 2608.25104 — arXiv, submitted 2026-08-25, paper. There are 9 authors, and we confirmed the affiliations in HTML v1.
- Kuaishou Technology (Beijing), 6: Chenghao Zhang, Chao Feng, Xunyong Yang, Xiang Li, Yongqi Liu, Kaiqiao Zhan
- USTC, 2: Yuanhao Pu, Defu Lian
- Kun Gai(Unaffiliated)
Background Today's industrial recommender systems widely adopt a Generator-Evaluator (G-E) architecture in the re-ranking stage. The generator produces several candidate lists, and the evaluator scores those lists and picks the best one. In short-video apps such as Kuaishou, users keep interacting over several requests within one session, but earlier evaluators optimized only a single-request metric for one list (for example, expected watch time) and so missed the view of the whole session. SWIM in this paper is an evaluator that scores a list by how much the current list contributes to the session objective.
What we learnedSWIM scores lists with a session-level survival process and was deployed to the Kuaishou main feed
- SWIM models user behavior as a finite-horizon prefix session-level survival process verified.
- It factorizes how much the current list contributes to the session objective into a recursive survival distribution and reached-position conditional rewards verified.
- It was deployed to production in the re-ranking of the Kuaishou main feed verified.
"Kuaishou short-video application (>400M DAU, >2 hours average daily engagement) ... 7 days, 5% traffic allocation" — SWIM HTML, 2026-08-25
- The exact figures are below verified.
- App stay time +0.351% (95% CI [0.27%, 0.42%])
- 7-day retention +0.048% (CI [0.01%, 0.09%])
- The deployment approach replaces the previous evaluator, CAVE, with SWIM, and keeps the upstream retrieval and generator unchanged.
Why notable SWIM is the third production recommendation paper Kuaishou has put out this month alone: the earlier two are PushDualGen and DrEM, while HD-Rec from the same month reported only benchmark results. This time the evaluator itself of the G-E architecture was redesigned as a session-level survival process, which is a different axis from the SID (semantic ID)/CoT debate or the pxtr noise debate. It appears to signal that the Kuaishou infrastructure team is revisiting the re-ranking evaluator literature across the whole stack inferred. However, the app stay improvement of +0.351% is large compared with other Kuaishou claims this month (for example, DrEM App Stay Time +0.116%); in effect, it explicitly sets a large room for evaluator-level intervention to affect downstream metrics.
Canon update Added a SWIM entry to the new this month section of radar.md.
Radar
Of 30 arXiv cs.IR papers triaged, 3 passed, and new evidence was attached to two watching threads.
- Added 3 entries to the new this month section of
radar.md: AMBER (Meta), TransRetrieval (Alibaba Alimama) and SWIM (Kuaishou). - The LLM-native ranking spread thread gained the angle of the Meta AMBER type (input encoder).
- The recommendation model scaling law thread received the first claim from the Alibaba ads line. As thread-body evidence, it is the company after Meta and Netflix.
What to check next
- Check the open questions remaining from Gen4+9.
- What are the production
save_concurrent_gbtuning value of ThrottledD2HArrayHandler and the increase in save time? - Under what conditions does
load_checkpoint_streamedreplaceload_checkpoint(v1)? The default restore still keeps v1. - Which config first activates warm_start_staging_spec, and has it already been applied to the flagship?
- Is there data showing that Manhattan reply_ranking's monotone-only write overturns the actual observed label flaps?
- After the VF media fallback cache was removed, what fraction of TES failures actually leads media features to fail closed?
- How are the training and serving of
ADS_PIXEL_FIREandADS_LONG_DWELL_AND_PIXEL_FIREconnected? They do not yet appear in recsys_model.py. - Who is the actual consumer of
conv_asset_ids? - When will
use_history_segment_idsbe promoted to production?
- What are the production
- Watch whether AMBER's A/B figures appear in a follow-up blog post or a paper revision — no online lift is stated in the abstract or the HTML.
- Watch whether other companies reproduce TransRetrieval and Alimama ads — if a third company's claim of scaling a retrieval stack appears, consider promoting it to the
topics/embedding-retrieval.mdsection.