Making Your Atom Feed Reliable: Stable IDs, Timestamps, and Content Choices
Ensuring your Atom feed works reliably means fixing the three core contract fields—immutable entry IDs, proper RFC 3339 timestamps, and correct content markup.
23 Sept 2026, 22:23 UTC

The Atom Contract: id, title, updated
Atom 1.0 defines a strict contract for each entry: an id that is globally unique and immutable, a title that describes the content, and an updated timestamp that signals a meaningful change. Feed readers compare the id with the updated value to decide whether to cache or fetch a new copy. Treat the id as a primary key and never reuse it for different content.
Choosing a Permanent, Globally Unique ID
Prefer a canonical URL such as https://example.com/posts/2026/11/12 or a tag URI derived from your domain and publish date, e.g., tag:example.com,2026-11-12. The identifier must stay the same for the life of the entry; reusing it creates duplicate or missing items in many readers. Never generate a new id when the content changes only in wording.
Timestamp as the Change Signal
Use the updated element, not published, as the change signal. Feed clients commonly compare id plus updated to detect updates, so bump updated whenever the substantive content changes. The value must be an RFC 3339 date‑time with an explicit offset, for example 2026-11-12T07:17:22Z.
Content Markup: xhtml vs html
Atom allows text, html, xhtml, and out‑of‑line content via src. For a technical blog, xhtml preserves markup structure but requires correct namespace wrapping and escaping of <, >, and & characters. HTML is simpler to write but less structured. Choose xhtml when you need strict formatting, otherwise html reduces escaping overhead.
Worked Example
A minimal entry that follows the contract looks like this:
<entry>
<id>https://example.com/posts/2026/11/12</id>
<title>Atom Feed Best Practices</title>
<updated>2026-11-12T07:17:22Z</updated>
<link rel="self" href="https://example.com/posts/2026/11/12"/>
<content type="xhtml" xml:base="https://example.com/posts/2026/11/12">
<![CDATA[<p>Technical notes about Atom feeds.</p>]]>
</content>
</entry>
The id is a permanent URL, the updated timestamp uses RFC 3339 UTC, and the rel=self link ensures clients resolve the link even if the feed’s base URL changes.
Trade‑off and Limitation
The main trade‑off is complexity versus compatibility. xhtml gives clean structure but forces you to escape special characters and manage namespaces, increasing the chance of well‑formedness errors. RSS, which many older aggregators still prefer, can be generated from the same data but lacks the explicit id‑updated contract, so you must add extra logic to keep them aligned.
Actionable Steps to Verify
- Create a two‑entry feed, parse with an XML validator, and confirm each entry contains id, title, updated, and a rel=self link.
- Round‑trip the feed through your generator and a feed reader; change only updated and ensure the reader treats the entry as changed, then change id and confirm duplication appears.
- Run an Atom validator (e.g., the W3C feed validator) and verify that relative links resolve via xml:base or absolute URIs.
- If you also publish RSS, generate both feeds from the same model and compare entry counts, ids, titles, and updated timestamps for consistency.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.