A while back we got called in on a small publisher whose articles kept showing up, word for word, on a site nobody had ever heard of. Same headlines, same images, same typos. The owner assumed someone was scraping the pages. They weren’t. They’d subscribed to the site’s own RSS feed, which was set to publish every post in full, and a script was reposting the whole thing within minutes of each publish. Nothing had been hacked. WordPress was just doing exactly what it had been configured to do since the day it was installed.
That’s the strange thing about feeds. Every WordPress site publishes them, most owners have never opened one, and the handful of settings that control them sit on a screen people visit once and forget. Your site is quietly syndicating your content to anyone who asks, in a format you’ve probably never inspected, at a length you probably never chose.
This guide covers what WordPress actually generates, where each feed lives, the two settings that decide how much of your work you give away, and how to change any of it without breaking the readers you do have.
Your Site Publishes More Feeds Than You Think
Ask most people where their RSS feed is and they’ll say /feed/. That’s true, and it’s a fraction of the picture. WordPress doesn’t generate one feed. It generates a feed for essentially every archive it knows how to build, on demand, from the same rewrite rules that produce your normal URLs.
Five feed slugs, four formats
Core registers its feed endpoints in a single array on the rewrite class: feed, rdf, rss, rss2, and atom. That’s five slugs you can append to a URL, but only four of them are distinct formats. The bare feed slug is an alias that resolves to whatever your default is, and core sets that default to rss2 through the default_feed filter.
So yoursite.com/feed/ and yoursite.com/feed/rss2/ return byte-identical output on a stock install. The other three are legacy or alternative standards. rdf serves RSS 1.0 in RDF form, rss serves the older RSS 0.92, and atom serves Atom 1.0, which is a genuinely separate specification rather than an RSS revision. Each one is a real template file sitting in wp-includes, and there are six of them once you count the two dedicated comment-feed templates.
If you ask for a format that doesn’t exist, core doesn’t guess. do_feed() checks whether a matching action has been registered and, if not, calls wp_die() with a 404 and the message that this is not a valid feed template. It’s one of the tidier bits of core: an unregistered feed is a hard miss, not a silent fallback.
Feeds for things that aren’t your blog
The part that surprises people is how far the pattern extends. Append /feed/ to almost any archive URL and you get a working feed for it. Your category and tag archives have feeds. So do author archives, date archives, custom post type archives, and search results. Comments get their own feed at /comments/feed/, and every individual post carries a per-post comments feed on top of that.
Nobody chose these. They come with the rewrite rules. WordPress advertises a subset of them in your page <head> automatically through two functions hooked to wp_head: feed_links() at priority 2 for the main site and comments feeds, and feed_links_extra() at priority 3 for the context-specific one, so a category page links its own category feed. Since WordPress 6.1 there’s a dedicated feed_links_extra_show_post_comments_feed filter if you want to suppress just the per-post comments link without touching the rest.
A feed is the only part of your site designed to be consumed by machines and republished elsewhere. Newsreaders, email digest services, aggregators, AI training crawlers and content scrapers all read the same endpoint. Whatever you put in it, you are handing out in a structured, easy-to-parse form — which is exactly why the full-text setting deserves more than thirty seconds of thought.
The Two Settings That Decide Everything
Almost all the meaningful control over your feeds lives on one admin screen: Settings, then Reading. There are only two fields, and both defaults were chosen for a web that looked very different.
Full text or excerpt
The field is labelled “For each post in a feed, include,” with two radio buttons: Full text and Excerpt. Core ships it set to Full text. In the database it’s the rss_use_excerpt option, where 0 means full text and 1 means excerpt, which is the sort of inverted naming you only notice when you’re setting it from the command line.
Full text is genuinely better for readers. Someone in a newsreader gets the whole article without a round trip, and the people who subscribe to feeds tend to be your most engaged audience. It’s also the setting that let that publisher’s entire archive get mirrored automatically. Excerpt mode cuts scrapers off at the summary and pulls readers to your site, at the cost of making the experience worse for the ones who wanted to read in their reader.
There’s no correct answer, only a trade you should make deliberately. A business site publishing a handful of posts a month gets very little from full text and carries the whole downside. A publication with a real subscriber base usually decides the reader experience is worth it. What you don’t want is to discover which one you picked by finding your own paragraphs somewhere else.
How many posts go out
The second field reads “Number of recent items shown in syndication feeds” and defaults to 10. That’s the posts_per_rss option, and it’s a cap, not a window into your whole archive. A feed is a rolling snapshot of what’s recent, which is why anything that reads feeds treats them as a discovery mechanism rather than a full index.
Raising it has a real cost. Every item in a full-text feed carries the entire post body, so a site that bumps this to 50 is generating a large XML document on every feed request. If your feed gets polled often, that’s meaningful bandwidth for content most subscribers already have. Ten to twenty covers nearly everyone.
Both settings are one command each if you’d rather not click:
wp option get posts_per_rss
wp option update rss_use_excerpt 1
wp option update posts_per_rss 20
/feed/ — main posts feed (RSS 2.0 by default)
/feed/atom/ — the same posts as Atom 1.0
/comments/feed/ — every comment site-wide
/category/news/feed/ — one category
/tag/pricing/feed/ — one tag
/author/jane/feed/ — one author
/?s=widgets&feed=rss2 — a search result
/your-post-slug/feed/ — comments on one post
How WordPress Actually Builds a Feed
Worth understanding if you ever need to change what goes out, because the answer is rarely “install something.”
Templates, not a page render
A feed request never touches your theme. Core resolves the requested format, fires a dynamic do_feed_{$feed} action, and that handler loads a template out of wp-includes directly. Your header, footer, sidebar and every theme function that would normally run are entirely bypassed. This is why a feed can keep working perfectly while a theme is visibly broken, and why “it looks fine in the browser” tells you nothing about feed output.
The filter that changes what subscribers see
Feed content runs through the ordinary the_content filter first, and then through the_content_feed. That ordering catches people out: anything you hooked to the_content already shows up in your feed, which is why a related-posts block or a signup CTA leaks into feed items nobody expected. the_content_feed is the hook for output you want in feeds only — an attribution line and a canonical link back to the original, or stripping something that makes no sense outside your layout. One caveat: with the excerpt setting on, items take the excerpt path instead and a the_content_feed hook won’t fire at all.
An attribution footer is the single most useful thing you can add here. It won’t stop anyone determined, but automated republishers copy the item body verbatim, which means they copy your link back too. That publisher’s stolen posts ended up carrying a credit line and a link to the original within a day of us adding a few lines to a plugin.
add_filter( 'the_content_feed', function ( $content ) {
$link = esc_url( get_permalink() );
$name = esc_html( get_bloginfo( 'name' ) );
return $content . '<p>Originally published at <a href="' . $link . '">' . $name . '</a>.</p>';
} );
Put that in a small site-specific plugin rather than your theme’s functions.php. Feed behaviour isn’t presentation, and you want it to survive the next redesign — code in a theme file stops running the moment you switch themes.
Registering a feed of your own
Core has exposed add_feed() since version 2.1, and it’s still the cleanest way to publish a custom endpoint. You give it a slug and a callback, it appends the slug to the rewrite feed list and wires up the matching do_feed_ hook. That’s how you’d expose a JSON feed of upcoming events, or a trimmed feed for one partner. Register it on activation and flush rewrite rules once, then leave it alone. WordPress’s own reference is blunt that flushing is an expensive operation and should only be used when necessary, so it has no business running on ordinary page loads.
Where Feeds Quietly Go Wrong
Three failure modes account for most of the broken feeds we come across, and none of them announce themselves.
A stray character breaks the whole document
XML is unforgiving in a way HTML isn’t. A browser will happily render a page with a malformed tag, but the XML specification classes any well-formedness violation, down to a single ill-formed byte sequence, as a fatal error — at which point a conforming processor must not continue normal processing. Lenient readers try to recover, strict ones simply stop handing you the document, so one stray character can take out the whole feed. The usual culprit is a plugin or a stray line in functions.php printing a notice, a warning, or a single blank line before the XML declaration. Your site looks perfectly healthy and your feed has been dead for months.
Check it by loading /feed/ in a browser and looking for a parser error, or by running it through the W3C Feed Validation Service. Both take about ten seconds and neither requires you to understand XML.
Two plugins fighting over the same output
SEO and social plugins sometimes modify feed content, add namespaces, or disable feeds outright. Run two that both have opinions and you can end up with duplicated elements or a feed that stops validating. If a feed broke around the time you installed something, that’s usually your answer.
Turning feeds off without redirecting them
Plenty of business sites have no real use for feeds, and disabling them is a defensible choice. Doing it by making the endpoints die is not. Anything subscribed to you gets an error forever, and any tool that discovers your feed URL from an old page keeps hitting a broken endpoint. If you’re switching feeds off, redirect the feed URLs to the equivalent page with a 301 instead, so subscribers land somewhere real.
Open /feed/ and confirm it parses. Check Settings → Reading and make the full-text-or-excerpt call on purpose. Confirm posts_per_rss is somewhere sane. Search a distinctive sentence from a recent post in quotes on Google to see whether anyone is republishing you. If they are, add an attribution filter before you start sending takedown notices — the link back is worth more than the fight.
Feeds, Search, and Everything Downstream
Feeds get dismissed as a relic, usually by people remembering the day Google Reader shut down. The format never went anywhere, because too much infrastructure depends on it.
Google’s own sitemap documentation still lists RSS 2.0 and Atom 1.0 feeds as an accepted sitemap format alongside XML and plain text, with the caveat that a feed only carries recent URLs rather than your full archive. Google will accept a feed as a sitemap in its own right; we’d still pair it with a full XML sitemap rather than lean on it alone, precisely because of that recent-URLs limitation. Either way, the feed your site already generates is a legitimate way to tell search engines about new content quickly. Feeds also drive podcast distribution wholesale, feed most email digest services, and remain the standard input for aggregators of every description.
None of that makes RSS a ranking factor, and you shouldn’t expect a feed to move your positions. Treat it as plumbing: a machine-readable copy of your recent work that other systems consume. Plumbing you’ve never inspected is worth an afternoon.
The broader habit matters more than the specific setting. WordPress generates a great deal you never explicitly asked for — feeds, archives, attachment pages, taxonomy listings — and each one is a real, crawlable, subscribable surface. Knowing what your install publishes is the difference between running a site and hosting one.
Frequently Asked Questions
If you’d rather someone else opened every feed your site publishes and told you which ones are wrong, that’s the kind of unglamorous audit we do all day.
Built by amplifi.studio — see also our WordPress author archives guide, on another set of pages WordPress creates whether you asked for them or not.