The Algorithm That Needs Users It Doesn't Have Yet.
I had a weighted ranking formula ready to implement for my feed before I had a single user to rank content for. I almost started writing the code anyway.
I was designing the recommendation logic for a social feature. “Just show the newest posts” wasn’t going to cut it, so I drafted a weighted score, the kind you’d see in any system design writeup:
feedScore =
0.35 * freshness +
0.30 * engagement +
0.20 * relevance +
0.10 * creatorFamiliarity +
0.05 * karmaBoost
It looked right. I had my editor open and was about to start implementing it.
Then I asked myself where 0.35 came from. Not whether it looked balanced on the page, whether freshness deserved more weight than engagement. Where the actual number came from. I didn’t have an answer, because there wasn’t one to have.
Relevance is supposed to measure how similar a post is to content the user already engages with. That sentence assumes a user with an engagement history. My app has zero users. There’s no history to compare anything to, and there won’t be one on launch day either.
CreatorFamiliarity has the same hole in it. It tracks whether someone follows or regularly engages with a creator. On day one, nobody follows anybody. Every value in that column is zero for every user, and stays zero until people actually start using the thing.
KarmaBoost needs creators with accumulated karma. Nobody’s posted yet, so there’s no karma to accumulate.
Three of five signals in my formula can’t produce a real value on launch day. Not a weak value. No value.
My first thought was to patch around it: set relevance to some neutral constant, zero out creatorFamiliarity, let the math degrade gracefully. It would still run. You’d get a number out the other side. But a formula that returns a number isn’t the same as a formula that means something. If every new user gets an identical relevance score because I made the number up, I haven’t personalized anything. I’ve built a slow way to sort by date.
This is the cold start problem, and it shows up anywhere something ranks or recommends: feeds, search results, product suggestions, matchmaking. You need behavioral data to weight the model. Behavioral data only comes from people using the product. People only use the product if it already works reasonably well. And it only works well if the ranking is already good, which is the thing you were trying to build in the first place. You can’t validate feedScore against real engagement until real engagement exists, and it won’t exist behind a feed that’s ranking things arbitrarily.
I was trying to build the smart version of the system before the dumb version had produced a single data point worth being smart about.
So the fix isn’t a better formula. It’s accepting that the weighted version is a second phase, one that only becomes possible once a simpler system has been running long enough to generate the inputs it needs. The actual first version isn’t a formula at all — it’s a short list of rules that don’t need any history to evaluate: show posts from creators the user follows, then posts from creators they’ve engaged with before, then popular recent posts from the wider community, with a small freshness boost so new content doesn’t get buried under old popular stuff.
Every one of those can be answered for a brand-new user with zero training data. Who you follow is knowable the second you follow your first account. What’s popular right now is knowable from raw counts, no model required. There’s nothing to learn in any of it, just retrieval and sorting.
I’d been treating that rule-based version as the placeholder you ship while waiting to build the real thing. It’s not a placeholder. It’s the mechanism that produces the dataset the weighted formula will eventually need: which posts got liked, which got skipped, which creators people kept coming back to. Log that from day one, and by the time the follow-graph feed feels too rigid, the numbers to justify a smarter one already exist.
If a signal in your formula can’t produce a real value without prior user behavior, it doesn’t belong in the formula yet. It belongs in your logging.
