What Politeness Actually Costs the Other Side
Every fetch you make is work somebody else pays for. A feed endpoint may be generated per request, and the publisher serving it is not being compensated by your reading. So the question is not "am I allowed to fetch this?" but "what is the cheapest way to learn whether there is anything new?"
HTTP answered that question decades ago and most aggregators still ignore the answer. When a server hands you a feed it usually also hands you validators: an entity tag, a last-modified timestamp, or both. Store them on the source row. Send them back next time as If-None-Match and If-Modified-Since. A server that has nothing new answers 304 Not Modified with no body at all — it does not render the feed, does not serialize it, does not transfer it.
Record 304 as Its Own Outcome
The subtle part is bookkeeping. A 304 is neither an error nor a successful ingest, and collapsing it into either one corrupts something. Count it as an error and your circuit breaker will eventually disable your best-behaved sources — the ones that update rarely and answer 304 most often. Count it as a successful fetch of zero articles and your logs will suggest a source has gone dry when it is merely quiet.
Give it a third status. The fetch log then tells you three genuinely different things: this source gave us articles, this source told us there was nothing new, and this source failed.
Serial Is a Politeness Feature
It is tempting to fan a fetch round out concurrently, and for your own latency it would help. But a round that hits forty sources in parallel is a small burst against whoever happens to host several of them, and the fastest way to get a private tool blocked is to look like a crawler.
A plain sequential loop over the enabled sources, sharing one client with a configured timeout and an identifying user agent, gives you per-host concurrency of one for free — not because you implemented a semaphore, but because there is only ever one request in flight. A fetch round taking twenty-odd seconds costs nothing, because nobody is waiting on it: the reader is served from the store.
Identify Yourself
Send a user agent that names the product and says what it is. This is not decoration. It is what lets an administrator looking at their logs distinguish a small private reader from an anonymous scraper, and decide accordingly. A tool that hides what it is has made a decision about how it wants to be treated.