← field notes

How a recommendation system decides what you see

recommendation-systems ranking retrieval feed-algorithms

A feed has to arrive before you notice you were waiting. Call it two hundred milliseconds for the round trip, network included. Scoring one item with a serious ranking model costs a fraction of a millisecond on the right hardware, which is fine until you point it at ten million items and land on a number measured in hours.

That arithmetic is the reason every large recommendation system you have ever used has the same skeleton. It is also why arguing about “the algorithm” as a single object gets nobody anywhere. There are at least three of them, and the one people fight about is the one that matters least.

I run mobile proxy lines on carrier SIMs in Singapore and a rack of Android phones people rent by the hour. I also publish on my own sites and channels most days, so I sit on both ends of this. I have never worked inside one of these companies. What follows is put together from published papers, patent language, engineering writeups, and years of pushing on the outside of the machine.

Three stages wearing one name

Stage one narrows. Hundreds of millions of items go in and a few hundred candidates come out.

Stage two orders those few hundred, using a model far too expensive to have been pointed at the original pile.

Stage three rearranges that order according to rules written by people, in code, with names attached.

Then the page renders. Everything strange downstream comes from stage two only ever seeing what stage one handed it.

Retrieval is where existence gets decided

The narrowing stage is a handful of cheap sources running in parallel, each holding a quota of slots.

One pulls recent items from accounts you follow. One pulls what is popular in your country and language this hour. One pulls items sitting near things you engaged with before, using an approximate lookup over a vector index, with no model reading anything. One works from behavioural clusters, groups of users who act the way you act, and returns what they touched that you have not seen. A couple more return things the system knows nothing about, deliberately.

Almost none of that is a judgement. It is a set of queries with limits bolted on.

Which produces the part people miss. If nothing in that union returns your item, it never reached the ranker. No model formed a low opinion of it. No model saw it. There is nothing to appeal, because no decision was taken: a query ran and your row was not in the result set.

Search “pasta” in a grocery app and the engine fetches maybe two hundred products out of forty thousand, then sorts those. A jar that never enters the two hundred is simply invisible, and no photograph fixes a retrieval query it does not satisfy.

What the ranker predicts, and who sets the weights

The second stage has no view on quality. It makes predictions, usually several at once, out of one shared model body.

Probability you click. Probability you are still there at thirty seconds. Probability you reach the end. Probability you like, reply, forward. Probability you hide it or report it.

Those come out as separate numbers and then get combined into a single score by a weighted sum. The weights are not learned. A person picks them, in a meeting, and revises them every few months.

That weight vector is the actual editorial policy of the platform, the nearest thing to a written answer to what the company wants from you, and it is never published. When a product changes character over a quarter and everyone assumes a new model shipped, the likelier story is that three numbers in a config moved.

The proxy problem

None of those predictions is the thing anyone actually wants. What a platform wants is for you to be glad you spent the time, and nothing in a log measures that. So it measures what leaves a trace: clicks, seconds, replies, shares. Those track satisfaction well enough to be useful and badly enough to be dangerous.

Lean on a measurable proxy hard enough and long enough and the measurement drifts away from the thing it was standing in for. The drift has a recognisable shape by now. Headlines promising something the article does not contain, because the promise is what gets clicked and the disappointment arrives after the click was logged. Comment sections that reward an argument, because an argument is engagement in a costume.

Nobody designed that. No rule rewards it. It is what a hill climbing process finds when the hill is slightly the wrong hill.

The platforms know, and the patches are honest. Survey cards asking whether that was worth your time. A not interested button. The trouble with all of them is volume: a survey answers back from a sliver of sessions while the click log takes billions of rows a day. A sparse signal nudges a model trained on a dense one. It does not overrule it.

Cold start, on both ends

Two kinds of newness break the pipeline in different ways.

A new user has no history, so most retrieval sources have nothing to query with. Population defaults fill the hole: country, language, device, whatever you tapped during onboarding, whatever is popular with everybody. That is why a fresh account gets the blandest possible version of a platform. It has nothing to join you to yet.

A new item is worse. The ranker predicts engagement from evidence and something published four minutes ago carries none. So the system does the only sensible thing available: a small allocation, shown to a slice, watched.

The slice is small, so the numbers coming back are noisy. A few hundred impressions is not much arithmetic to hang a future on. A good early sample puts the item into more retrieval pools, which earns more impressions, which produces more evidence, and the loop runs again in its favour. A flat one does none of that.

This is the entire mechanism behind the thing every creator repeats about the first hours deciding everything. They do decide a lot. Nobody chose that. An item’s only evidence is what it earned in that window, and the window was always going to be too small to be reliable. Two near identical items can land on opposite sides of it, and I have no comforting way to say that.

Some of what you see is a probe

A system that only ever serves its best current guess learns nothing and narrows into a corridor. So a fraction of what you get is a deliberate test, sampled to see what comes back. The framing is old: a set of options, unknown payoffs, and a budget split between finding out and cashing in.

Two things follow. The odd item in your feed, the one that made you wonder what the machine thinks you are, is sometimes not a claim about you. And if you publish, part of your result is a draw from a lottery the platform is running on purpose. Read too much into one outcome and you will change something that was working on the strength of noise.

Trained on its own past choices

The model learns from logs. The logs record what happened to items that were shown. What was shown was chosen by the previous version of the same model.

So it learns your preferences filtered through its own earlier decisions. It has outcome data for what it decided to try, and nothing for everything else, and nothing is not the same as bad.

Position compounds it. The item at the top of a list gets clicked because it is at the top, and the model reads those clicks as merit. There are real corrections, mostly weighting each training example by how likely the old system was to show it. They help. They do not close the loop, and the loop keeps turning while you work on it.

The layer with fingerprints on it

Then the ordered list reaches the last stage, and this is the one worth being angry about.

Ads go in, at fixed positions or by winning an auction against the organic item they displaced. No more than two items from one publisher inside a screen, to stop a feed becoming one account shouting, which is why somebody’s best performing piece sometimes suppresses their next one. Whole categories get demoted instead of removed until being down and being gone are the same thing. Freshness and items from your own network get forced in. Commercial arrangements get honoured. Legal removals apply per country, which is why the same query returns different worlds depending on where it came from.

None of that is learned. It is deterministic code, written by identifiable people, reviewed in a pull request, and it can overturn everything the model concluded. When someone says the algorithm is biased, the machine learned part is usually the least opinionated component in the stack. The opinions live in the weight vector and in that file.

What I had wrong

I assumed the ugly parts were emergent. My picture was a model that had quietly worked out which things pay and started leaning, unsupervised, with nobody accountable. It is a satisfying story because it makes the machine the villain.

The more I read about how a serving path is actually assembled, the less of that survived. The commercial behaviour is the least mysterious layer in the system. It is conditions in code, with names, in a file somebody owns.

I was also wrong in a way that cost customers time. When a thing stopped appearing I would tell them they had been demoted, and we would go and work on the thing. Sometimes nothing had been judged at all. The item had simply stopped matching whatever narrowing query used to include it, and we spent a fortnight polishing an object nothing was reading.

What I still cannot give you is the weighting: how much of a final position is predicted click against predicted completion against the diversity rule against the ad load that hour. Nobody outside those teams can, it differs per product, and it moves.

The audit everyone asks for points at the wrong stage

The usual demand is to publish the ranking model, which aims at the middle. A published ranker gets gamed inside a week and tells you little anyway, because a weight vector without its training distribution is close to meaningless.

The stages worth prying open are the first and the last. Which candidate sources ran, how many slots each held, and which rules fired on the result. Those are short answers to answerable questions, and they are the two places that decide whether a thing exists for you at all.

More on the machinery running underneath the ordinary internet at The Hidden Internet.

Get new guides and videos first — join the Telegram channel.

watch
The Hidden Internet on YouTube

Every field note starts as a short documentary. Watch the systems in this piece explained on screen.

subscribe →
read on
More field notes

The rest of the series on how the modern internet detects, tracks, and sorts the traffic that reaches it.

browse the archive →