The Feed Algorithm
A feed that earns the scroll — ranking as configuration, not a data-science moonshot.
The incident
The feed was chronological because chronological was easy. As content volume grew, the good posts drowned in the noise. Users learned that the tenth item was never worth reaching, stopped scrolling, then stopped opening the app. The content was fine. The ordering was the churn.
Why the obvious approach fails
Chronological ordering treats all content as equally valuable, which is false the moment volume grows. But the usual overcorrection — 'we need machine learning' — turns a ranking problem into a twelve-month research project with a cold-start problem and no explainability. The middle path has existed since the early social feeds: a weighted scoring function over signals you already have. Recency, affinity between viewer and author, and content-type weight get you most of the value of a learned model, with behavior you can read, tune, and explain — which matters when the business asks why a post ranked where it did.
The standard
- Feed ordering is a scoring function, not a timestamp sort: score = affinity × content-weight × recency-decay, computed per viewer.
- Decay is explicit and tunable — old content sinks on a curve you chose, not by accident.
- Fixed slots are deterministic: pinned posts, announcements, and sponsored items occupy declared positions regardless of score.
- Scoring weights are configuration, changeable without deployment, and every change is logged.
- Feed quality is measured: scroll depth and engagement-per-position are tracked so ranking changes are judged by data, not vibes.
How Cortex validates it
At plan time
feed features declare their signals, weights, decay curve, and slot rules before build.
At validation
assert: feed_order == f(affinity, weight, decay) — not created_atassert: pinned_slots.position == declaredassert: weight_changes.logged == trueAssertion syntax is illustrative.
At review
the approver sees a seeded-corpus ranking run: the same content set ordered for three different user profiles, each ordering traced to its scores.