TL;DR
- On the afternoon of October 30, I imported 3 subscriptions and got an empty timeline. Every RSS feed I checked, big channels included, returned 404.
- Channels I'd fetched before fell back to the API, but new channels were blocked from the fallback, a rule meant to stop made-up channel IDs from burning quota.
- Now a new channel's existence is checked first for 1 unit, and only real channels get the fallback. If that still fails, the page says so.
Plainfeed shows new videos from the YouTube channels you pick, in upload order, with no recommendations and no Shorts. The video list comes from YouTube's free RSS feeds, and the YouTube API only steps in for that list when RSS fails. This is a short note about the day RSS failed all at once.
- RSS: a free, undocumented URL per channel listing its recent videos (
/feeds/videos.xml?channel_id=…), 15 in my testing - Unit: the API's quota currency, 10,000 a day. Both methods in this post cost 1 unit per call
- Fallback: fetching a channel whose RSS failed from the API's uploads playlist (
playlistItems)
What happened
On the preview site I imported 3 subscriptions with my Google account, and the timeline stayed empty. The server cache had all three marked "couldn't fetch" at 15:43 and 15:46 (Korea time).
Around 15:50 I opened the RSS URLs directly from my Mac. Those three returned 404, and so did big channels like Google's developer channel, while the channel pages themselves loaded fine. When I tried again at 16:08 the feeds were back. I don't know exactly when it started or ended.
It wasn't the first time. The RSS reader Feeder's help page says YouTube's feed server sometimes answers every feed with 404 for hours, and a user thread on Google's AI developer forum has reported intermittent RSS 404s since late December 2025, with no answer from Google.
Why the page was empty
In short: channels I'd fetched before held up. Only new channels went blank.
The live site had 40 channels cached at the time. When RSS fails for a channel like that, the server shows the cached list or falls back to the API.
New channels were different. No fallback, just "couldn't fetch" for an hour. The rule existed so nobody could send a pile of made-up channel IDs and drain the fallback quota, but during an outage like this it leaves a brand-new visitor's first screen empty for an hour. The rule was right for existing users and wrong for new ones.
The fix
In short: check that a new channel exists first, then fall back only for real ones.
New channels whose RSS failed are collected and sent to channels.list in one call. One call covers many channels for 1 unit (this site sends at most 30 per request), and only the channels YouTube returns get the uploads-playlist fallback (1 unit each). Made-up IDs come back empty, so they can't spend fallback quota, and the same response fills in channel names and avatars, so there's no second lookup.
// Trimmed code (lib/youtube.js) const unchecked = results.filter((r) => r.check); // new channels whose RSS failed if (unchecked.length) { const found = await channelsList(unchecked.map((r) => r.id)); // 1 unit for (const r of unchecked) { if (!found.has(r.id) || fallbacks >= maxFallback) { r.dead = true; continue; } // retry in 1 hour fallbacks++; r.feed = await fetchUploads(r.id); // 1 unit } } The fallback keeps the limits it already had: 6 channels per request (shared with known channels), and per day 1,000 channels in total and 200 per requester (1 unit each). The 1-unit existence check counts against the daily budget for new channels.
In short: if a channel couldn't be fetched, the page says so.
Before, the page said "No new videos" even when nothing had been fetched at all. That was wrong. Now, if nothing came back, it shows only the notice below, and if some channels failed, it says how many.
What it costs
| When RSS fails (new channels only) | Before | Now |
|---|---|---|
| 3 new channels | 0 units (empty for up to 1 hour) | 4 units (check 1 + fallback 3) |
| 30 new channels | 0 units (empty for up to 1 hour) | 7 units (check 1 + fallback 6) |
| 30 made-up channel IDs | 0 units | 1 unit (check only) |
Duration lookups for the fetched videos (1 unit per 50, so up to 2 units for 6 channels) aren't in the table. Made-up IDs always get 404 from RSS, outage or not, so each such request now costs 1 unit even on a normal day, capped by the daily budget for new channels.
What I didn't change
- The fallback is still 6 channels per request. Import 30 subscriptions during an outage and you see 6 first, with the rest retried an hour later. The number fits the free plan's 50 external calls per request: RSS 30, fallback 6, check 1, video info 9, channel info 1 (47 total).
- The one-hour "couldn't fetch" mark stays too. Even after RSS comes back, those channels aren't retried until the hour is up.
- The preview site has no API key, so the fallback doesn't run there. I verified it with tests against fake YouTube responses instead.
Wrapping up
When you lean on free RSS, you have to plan for RSS stopping entirely. A rule that only took care of known channels was really only protecting people who were already using the site. Next time: how all these limits fit inside a single Cloudflare free plan.
