Noticed while auditing marketingFilter sources for #2168 (item 5c). No action needed today — filing so the interaction is written down before someone runs a backfill and is surprised by it.
The observation
clickhouse-blog's RSS window exposes far more history than we've ingested:
| source |
feed items |
stored |
gap |
| clickhouse-blog |
822 |
379 |
443 |
| val-town-blog |
109 |
174 |
— |
| pulumi-blog |
50 |
100 |
— |
| dbt-blog |
25 |
71 |
— |
It's the only one of the six active feed/video marketingFilter sources with a gap; the others have stored ≥ feed window. The newest 8 ClickHouse items are all stored and there are no marketing-filter-cap-tripped events in 14 days, so steady-state ingest is healthy — the 443 are old backlog outside the ingest window, not a stuck fetch. Nothing is broken.
I did not check whether this generalizes beyond the marketingFilter set. If someone wants to know how much feed history we're leaving on the floor registry-wide, that's the sweep to run.
Why it's worth writing down: backfilling this source would bypass the marketing filter
clickhouse-blog has marketingFilter on for a reason — its feed mixes product news with newsletters, competency announcements, and customer stories. Both backfill routes drop that protection:
- Bulk fetch trips the cap and inserts unfiltered.
MARKETING_CLASSIFIER_MAX_PER_FIRE = 20 (poll-fetch.ts:1147). Above it, classifyMarketingForReleases logs marketing-filter-cap-tripped and returns an empty map (:1226-1233). Downstream, marketingMap.get(index) is then undefined for every row (:1498), so nothing is suppressed and everything inserts visibly. The cap is a cost guard, and its failure mode is fail-open by design — fine for a 0–5 item feed delta, wrong for a 443-item backfill.
- The
/batch and workflow paths never classify at all. Neither routes/releases-batch.ts, workflows/backfill-source.ts, nor adapters/scrape-persister.ts reference the classifier — it lives only in the fetchOne path. So a local-ingest or backfill-source run skips it outright.
Net: any obvious way to pull those 443 in lands ~443 unfiltered marketing posts in the index — the exact outcome the filter exists to prevent. The existing escape hatch is the one named in the code comment: insert, then suppress after the fact via the suppress API.
If we ever do want this history
Options, roughly in order of preference:
- Leave it. 443 mostly-marketing posts from a source we already track live is low value against the cleanup risk. This is my recommendation.
- Backfill with an explicit classification pass — raise the per-fire cap for a one-off, or run the classifier over the candidate set before insert. Costs ~443
google/gemini-2.5-flash-lite calls, which is cents, but needs the code path to exist.
- Backfill unfiltered into
suppressed=1, then unsuppress the real product news. Safe default, manual review.
Reproducing the numbers
['releases-cloudflare-logs']
| where ['body'] contains 'marketing-filter-cap-tripped'
| extend p = parse_json(['body'])
| project _time, slug = tostring(p['sourceSlug']), candidates = toint(p['candidateCount'])
The gap itself is feed-vs-DB: pull the source's metadata.feedUrl, extract item-level <link>s, and diff against SELECT url FROM releases WHERE source_id = .... Note a feed's <link> set includes non-item links — scope the regex to inside <item> / <entry> blocks or the count comes out ~2× too high.
Noticed while auditing
marketingFiltersources for #2168 (item 5c). No action needed today — filing so the interaction is written down before someone runs a backfill and is surprised by it.The observation
clickhouse-blog's RSS window exposes far more history than we've ingested:It's the only one of the six active feed/video
marketingFiltersources with a gap; the others have stored ≥ feed window. The newest 8 ClickHouse items are all stored and there are nomarketing-filter-cap-trippedevents in 14 days, so steady-state ingest is healthy — the 443 are old backlog outside the ingest window, not a stuck fetch. Nothing is broken.I did not check whether this generalizes beyond the
marketingFilterset. If someone wants to know how much feed history we're leaving on the floor registry-wide, that's the sweep to run.Why it's worth writing down: backfilling this source would bypass the marketing filter
clickhouse-bloghasmarketingFilteron for a reason — its feed mixes product news with newsletters, competency announcements, and customer stories. Both backfill routes drop that protection:MARKETING_CLASSIFIER_MAX_PER_FIRE = 20(poll-fetch.ts:1147). Above it,classifyMarketingForReleaseslogsmarketing-filter-cap-trippedandreturns an empty map (:1226-1233). Downstream,marketingMap.get(index)is thenundefinedfor every row (:1498), so nothing is suppressed and everything inserts visibly. The cap is a cost guard, and its failure mode is fail-open by design — fine for a 0–5 item feed delta, wrong for a 443-item backfill./batchand workflow paths never classify at all. Neitherroutes/releases-batch.ts,workflows/backfill-source.ts, noradapters/scrape-persister.tsreference the classifier — it lives only in thefetchOnepath. So a local-ingest orbackfill-sourcerun skips it outright.Net: any obvious way to pull those 443 in lands ~443 unfiltered marketing posts in the index — the exact outcome the filter exists to prevent. The existing escape hatch is the one named in the code comment: insert, then suppress after the fact via the suppress API.
If we ever do want this history
Options, roughly in order of preference:
google/gemini-2.5-flash-litecalls, which is cents, but needs the code path to exist.suppressed=1, then unsuppress the real product news. Safe default, manual review.Reproducing the numbers
The gap itself is feed-vs-DB: pull the source's
metadata.feedUrl, extract item-level<link>s, and diff againstSELECT url FROM releases WHERE source_id = .... Note a feed's<link>set includes non-item links — scope the regex to inside<item>/<entry>blocks or the count comes out ~2× too high.