On June 11, 2026, build 11 of WhatNext. went to Apple for review. Eight days later, with that build sitting approved and ready to ship, I made the call to hold it back, reset the review clock, and resubmit a different build instead. Nobody made me do it. Apple hadn't rejected anything. The reason was a bug in the recommendation engine's cold-start math that I'd only just found, and I decided a delayed launch was worth less than a broken first impression.

A Feed That Never Changed

The app's mood and tag onboarding screen, where users pick from Tone, Energy, Vibe, and Theme tags instead of rating individual films

WhatNext. offers two ways to get started: rate a handful of films you already know, or skip straight to picking moods and genre tags if you'd rather not sit through ten ratings first. A user came back with a report that sounded, at first, like it had to be wrong: no matter what they picked on the mood and tag path, their discovery feed looked the same. Different moods, different genres, identical movies.

It wasn't wrong. Every user who onboarded that way was getting the exact same feed: the catalog average, regardless of selection. It took a moment to confirm because the feed wasn't frozen or obviously broken, just identical to what anyone else with an empty rating history would see.

What Shrinkage Was Already Doing

The root cause lived in a piece of math the recommendation engine had used since a much earlier session, called shrinkage. The idea itself is sound and still in use everywhere in the app: at a low rating count, your taste profile alone isn't confident enough to trust completely, so the engine blends it with a broader prior, the average taste of the whole catalog, and leans more on your own profile as your rating count grows. The blend shifts gradually: a profile with zero ratings gets essentially no weight, and a profile with a few dozen ratings gets nearly all of it.

That ratio is exactly what broke the mood and tag path. Onboarding that way saves your taste selection as a seed vector, but it saves it with a rating count of zero, since you haven't actually rated anything yet. Zero divided by anything is zero, so the shrinkage math multiplied every mood-and-tag seed by zero and threw it away, in full, before a single recommendation was ever scored. What was left was the catalog average, dressed up as a personalized feed.

The rating-onboarding path never had this problem. Rating ten seed films sets a real, non-zero count from the start, so its version of the same formula behaved correctly the whole time. The bug only existed on the path where the count is honestly zero and always was.

The Fix: The Seed Becomes the Prior

The tempting fix was to fake a non-zero count for a mood-and-tag seed, just enough to unstick the math. I didn't take it, because that same rating count quietly feeds several other parts of the app, not just shrinkage. Faking the number to fix one thing would have thrown off the others.

The discovery feed produced from the mood and tag selections shown above, after the fix: Dead of Winter, If I Had Legs I'd Kick You, and Beau Is Afraid

The actual fix changes what the shrinkage math blends toward. Instead of always falling back to the flat catalog average, the seed vector itself becomes a personalized prior, a blend of 85 percent your mood and tag selection with 15 percent the catalog average as a safety floor, so it's never resting on a single arbitrary choice alone. At a rating count of zero, that personalized prior is effectively the entire query, since there's nothing else yet to blend it with. As real ratings come in, the same shrinkage ratio that always existed starts pulling weight toward your rated taste instead, and the seed's influence fades out smoothly rather than vanishing at the first rating the way it used to.

I checked this against a real profile: at zero ratings, the recommendation query now closely reflects the actual seed selection, instead of the old bug's flat catalog average no matter what was picked. Two different mood-and-tag selections, run through the fixed math, produced clearly distinct results. And the handoff behaves the way it's supposed to: the seed's influence is strong right away and fades out gradually as real ratings come in and take over.

The Trade I Almost Didn't Make

The straightforward plan, the day the bug was found, was to ship the already-approved build as-is and treat the fix as a fast-follow update a few days after launch. For a few hours, that was the plan. New users would see a degraded feed for maybe their first ten ratings, then a quiet update would land and quietly correct it going forward.

I couldn't get comfortable with that. A new user's first ten ratings are exactly the window where they're deciding whether the app actually understands what they're asking for, and the honest answer, under the bug, was that it didn't understand anything at all for anyone who used the faster onboarding path. Shipping that on purpose, with a fix already sitting written and tested, felt like choosing a launch date over the actual first impression the app was built to give.

So the build changed. What had been queued as version 1.0.1, a fast-follow patch on top of an already-shipped 1.0.0, became the new 1.0.0 itself, folded in alongside a batch of other quality fixes that had accumulated on the same branch. That meant giving up build 11's approval entirely and resubmitting a new build from zero, resetting Apple's review clock with no guarantee the next round would go any faster. It did cost real time. It also meant nobody who downloaded WhatNext. on day one ever saw the version of the recommendation engine that quietly ignored their own taste.

Where This Doesn't Fully End

Fixing the zero-count bug didn't turn off shrinkage itself, and it wasn't meant to. The tradeoff shrinkage exists to manage is still there by design: a genuinely niche taste that happens to sit close to a much more common one in the recommendation engine's understanding of tone and theme can still read as somewhat generic for roughly the first 30 ratings, while the engine gathers enough signal to tell the two apart confidently. That's a known, documented limitation of leaning on a broad prior at all, not a bug, and it's one I'd rather describe honestly than pretend the June fix made disappear.

What changed is narrower and, to me, more important: the mood and tag path now actually starts from what you told it, instead of discarding that information before it ever reached your first feed.