A release notes template gives every release a fixed structure (version, summary, features, fixes, breaking changes, migration steps, deprecations, and known issues). Any reader then finds what matters in 30 seconds. Most templates online are markdown stubs with five empty headings. That is enough for the first release. It is not enough for the tenth. By then the same release needs to appear as a developer changelog, a customer email, and a PDF for the compliance team.
This article gives you the full template and explains why each section earns its place. Three real-world examples follow, plus the conditional-content pattern that publishes one source to both audiences. The format details are not stylistic preferences. Keep a Changelog, semantic versioning, and the ISO 8601 date format each define part of what readers expect.
What release notes are - and what they are not
Release notes are scoped to a single versioned release. They answer four questions for a reader who already decided to use the product. What shipped, what changed, what broke, and what to do about it. The audience is whoever consumes the release. For an API that is developers. For a SaaS product it is both developers and end users. For an internal tool it is the operations team that owns it.
Release notes are not a changelog and not a what's new page. The three overlap. The distinctions matter for tooling and audience selection. A changelog is a rolling list of every change across all versions, usually terse and developer-oriented. A what's new page is a curated, narrative summary aimed at end users, typically with screenshots and a marketing tone. Release notes sit in the middle: scoped like a changelog, audience-aware like a what's new page, and complete on their own.
| Document | Audience | Scope | Tone | When to use |
|---|---|---|---|---|
| Release notes | Both developer and customer | One versioned release | Direct, categorical | Software with discrete releases that need migration or known-issue tracking |
| Changelog | Developers | All versions, rolling | Terse, technical | Libraries, APIs, CLI tools where the audience reads diffs |
| What's new | Customers and prospects | Curated highlights | Narrative, image-led | Consumer SaaS, in-app announcements, marketing surfaces |
Teams that publish a CHANGELOG.md in the repo and call it done are publishing a changelog, not release notes. That is defensible for an open-source library with one audience. It breaks the first time a customer asks what is new. Nobody reads a list of internal refactors to find out.
The release notes template (copy this)
Use the structure below for any release. Replace the bracketed placeholders. Keep the section order. Readers scan the same locations every release, and reordering punishes them.
# [Product] v[X.Y.Z]
Released: YYYY-MM-DD
Status: [GA | Beta | Preview]
Audience: [Developers | Customers | Both]
Previous: [Link to previous release]
## Summary
[One or two sentences. What did this release ship and who should care?]
## New features
- **[Feature name]**: [Who it is for]. [One-sentence description]. [Docs link]
- **[Feature name]**: [Who it is for]. [One-sentence description]. [Docs link]
## Improvements
- [What changed and what is the user-visible effect]
- [What changed and what is the user-visible effect]
## Bug fixes
- [Fixed: what was broken, what is fixed]. [Internal ID]
- [Fixed: what was broken, what is fixed]. [Internal ID]
## Breaking changes
- **[Change name]**: Before: [old behavior]. After: [new behavior]. Affects: [endpoint, surface, or feature].
## Migration steps
1. [Action]. [Expected result.]
2. [Action]. [Expected result.]
```diff
- oldApi.deprecatedMethod(payload)
+ newApi.replacementMethod(payload, { version: '2024-10-01' })
```
## Deprecations
- **[API or feature]**: Deprecated: YYYY-MM-DD. Removed: YYYY-MM-DD. Replacement: [link to replacement].
## Known issues
- **[Issue]**: [Symptom]. [Workaround, if any]. [Tracking ID].
The template is intentionally plain. Visual styling belongs in the rendered output. The same release may publish as an in-app changelog widget, a docs-site page, a customer email, and a PDF for the compliance archive. Four different stylesheets format the same content. The template is the content.
Why each section earns its place
Generic release-notes templates list these sections without explanation. The explanation is what tells you when you can drop a section and when you cannot.
Header block
Version, release date, status, audience, and a link to the previous release. The version is the foreign key. Every support ticket, every diff comparison, every documentation cross-reference resolves through it. The ISO 8601 date format (YYYY-MM-DD) sorts correctly and removes locale ambiguity. That ambiguity costs an hour when a US team and an EU team disagree about what "06-05" means. The status field signals whether features are GA, Beta, or Preview. That matters when a customer wonders why a feature in the release notes is not in their account.
Summary
One or two sentences answering "what shipped and who should care." The summary is what readers scan before deciding whether to keep reading. Without it, the release notes open with a list of feature names. A reader who only wants to know whether their migration path changed must scan the whole document. The summary is the answer that lets them stop reading.
New features
Each entry names the feature, states who it is for, gives a one-sentence description, and links to the documentation. The link is mandatory. A feature without docs is not ready to announce. Adding it to release notes generates support tickets the docs team cannot answer. The "who it is for" qualifier prevents the second-largest category of support tickets. That category is customers asking why a feature they cannot use yet appears in their release notes.
Improvements
Improvements are non-breaking changes to existing behavior. Performance gains, UI polish, accuracy fixes, capability expansions that do not change contracts. They belong in their own section. Mixing them with bug fixes obscures whether the release is risk-free or behavior-changing. A reader asking "is anything different about how my integration responds" reads Improvements. A reader asking "was the bug I filed fixed" reads Bug fixes.
Bug fixes
What was broken, what is fixed, and the internal reference ID if one exists. The ID lets customers map the fix back to the ticket they filed three months ago. That closes the support loop. The phrasing matters. "Fixed the calendar timezone bug" is a release note. "Fix calendar tz" is a commit message. Release notes are written for users, in past tense, from the user's perspective.
Breaking changes
A dedicated section, never mixed into improvements or bug fixes. Each entry states what breaks, what to do, and which versions or surfaces are affected. Hiding a breaking change inside another section is the single most common cause of post-release support escalations. It also loses the most trust per incident. If a release contains no breaking changes, the section reads "None in this release." Silence in this section creates the wrong inference.
Migration steps
Numbered. Code-block diffs where applicable. Prose migration instructions get misread. A diff block showing - old and + new does not. Each step has one action and one expected outcome. The same discipline applies to SOPs and runbook entries. The reader's question is not "how should I think about this migration." The question is "what shall I type." The steps answer the second question.
Deprecations
Every deprecation has two dates: deprecated on (when the warning starts) and removed on (when the feature stops working). Without the removed-on date, downstream consumers cannot plan their migration window. The deprecation becomes a permanent warning. Permanent warnings get ignored. The Stripe API changelog publishes both dates as standard practice. That is one of the reasons their long migration windows actually convert to upgrades.
Known issues
Symptoms, workarounds, tracking IDs. Known issues are the part of a release note that wins trust. A team that publishes its known issues with workarounds is telling you something. It tracks what is broken, and it is honest about it. A team that ships release notes with no Known Issues section is either too small to need one or pretending nothing is wrong. The second is much more common and much more costly.
Three examples of release notes done well
The examples below are public, dated, and structured. Each one solves a specific problem worth copying.
Stripe API changelog
The Stripe API changelog versions every API change by date, for example the 2024-10-28.acacia version. Each entry lists what changed, what breaks, and how to upgrade, with separate notes for the API and the Dashboard. Three things make it work. First, dated versions decouple the release schedule from semantic-version drama. Every API consumer pins to a date and upgrades on their own timetable. Second, breaking changes get their own section per version, never mixed into additions. Third, every entry links to the docs for the surface that changed. A reader verifies the new behavior in two clicks. The audience is developers and the format reflects it. Terse, factual, no marketing language.
Linear changelog
The Linear changelog takes the opposite end of the audience spectrum and does it equally well. Each release is a dated post, customer-facing, with short narrative paragraphs. Embedded screenshots or GIFs show the change in product. The cadence is roughly monthly. The format works because Linear knows its readers. They are product-minded users who care what a feature looks like, not engineers reading an API diff. Two specifics are worth copying. The post-style entries are timestamped at minute precision, so the changelog doubles as a public dev-log. A clear "Improvements" section quietly handles the boring half of every release without burying it.
Kubernetes release notes
The Kubernetes release notes handle the hardest version of this problem. An open-source project with thousands of contributors, breaking changes across multiple API groups, and a deprecation pipeline that spans years. Each release page leads with "Urgent Upgrade Notes (No, really, you MUST read this before you upgrade)". That header signals deprecation urgency in a way no marketing-flavored release note ever does. Deprecations are dated to specific minor versions. Every change is attributed to a contributor and a pull request. The format is exhaustive and unbeautiful. It works because the audience is operators who need traceability, not a customer who needs delight.
What bad release notes look like
The most common failure mode is the auto-generated commit log. A release page lists 40 entries that read fix: bump dependency, chore: update lint config, refactor: extract helper. Every entry is technically true and useless to every reader. Engineers cannot tell what broke. Customers cannot tell what is new. The page is evidence that the team shipped something. It is not communication about what shipped.
The second failure mode is the marketing announcement. Three paragraphs of "We're excited to bring you our biggest update yet" with no version number, no list of changes, no migration steps. The reader who wanted to know whether their integration breaks gets nothing actionable. The reader who wanted to celebrate the new feature gets a wall of adjectives. Both leave to file a support ticket.
The third is the internal-Confluence-only release page, titled "Release 4.2" with a list of Jira IDs and no narrative. It satisfies the engineering process but never reaches the customer. The customer hears about the release from a support agent. That happens the next time they ask why something behaves differently.
All three fail for the same reason: nobody wrote them with a specific reader in mind. A release note that works names its reader in the audience field at the top. Every entry is then written for that reader. The template above forces that decision before the writing starts.
The two-audiences problem
Most products ship one release to two audiences. Developers want breaking changes, API additions, and migration steps. Customers want features that affect their daily work and fixes for bugs they reported. The two groups scan different parts of the document. They read with different urgency and tolerate different amounts of detail.
Four wrong solutions show up repeatedly. One: a single technical changelog for both audiences. Customers stop reading after the third "deprecated SDK helper" entry. They bounce to support asking what is actually new. Two: two separate documents written by two teams. The marketing-owned customer doc ships two weeks late. The developer doc says v2.4 includes feature X. The customer doc says v2.4 has "exciting improvements." Neither mentions the breaking webhook signature change. Three: marketing-only announcements with no breaking-change information. Engineers discover the breaking change from production incidents. Four: tag everything as engineering and hope customers read past the API entries. They do not.
The pattern that holds up is conditional content. One source release note. Every entry tagged with an audience attribute — developer, customer, or both. At publish time, the developer channel filters to developer + both, and the customer channel filters to customer + both. Same template, same release date, two outputs. When the source updates, both outputs update together.
A concrete example. Version 2.4 ships a webhook signing key rotation. The developer entry reads: "New webhook signature algorithm — HMAC-SHA256 with rotating secrets, valid for 24 hours. Existing endpoints continue receiving the legacy signature until 2026-12-01. Migrate signature verification per docs/webhooks/v2 by that date." The customer entry, generated from the same source by filtering on audience tag, reads: "Improved webhook security with rotating signing keys. No action required — existing integrations continue working. Contact support if your platform sets policies on third-party signature verification." Same release, same date, two readers, both informed about what is relevant to them.
This pattern only pays off above a threshold. A team shipping fewer than 10 releases per quarter to a single audience is better off with a CHANGELOG.md in the repo. The complexity earns its keep when developer and customer audiences read in different channels. That means an in-app changelog widget, an email digest, a docs site, and a PDF for compliance. And it means the team is no longer willing to write four versions of the same release note. At that point the conditional-content approach is the difference between two outcomes. One is structured authoring without DITA XML. The other is a Notion page that drifts from the in-app widget within two releases.
Best practices checklist
The list below is what consistently distinguishes release notes that get read from release notes that get ignored. None of it is decoration.
- Use ISO 8601 dates (YYYY-MM-DD). Sortable, unambiguous across locales, machine-parseable.
- Reference semantic versioning or CalVer consistently. A MAJOR bump signals breaking changes. Readers who know the convention skip half the document when you signal correctly.
- Keep section order identical across releases. Readers learn where to scan once and rely on that map for every subsequent release.
- Write each entry in past tense from the user's perspective. "Fixed the calendar timezone bug" is a release note; "Fix calendar tz" is a commit message.
- Link every entry to its documentation. A feature without docs is not ready to announce. The link lets a reader verify the change in context.
- Put migration steps in code blocks with diffs. Prose migration instructions get misread; diffs do not.
- Date every deprecation with both deprecated-on and removed-on. Without the second date, deprecations become permanent warnings that get ignored.
- Treat published releases as immutable. Corrections go in a follow-up release, not in an edit to the original. Editing a published release destroys the audit trail.
- Maintain an Unreleased section while the next version is in development — the Keep a Changelog convention. It removes the writing-debt problem at release time.
- Tag every entry with audience for conditional publishing. Even with one channel today, the tag costs nothing. It earns its place the first time you spin up a second channel.
- Skip marketing language. Release notes are for users who already chose the product; persuasion is wasted on them.
- Never let a breaking change ship without a release note that names it. Every other rule on this list has exceptions. This one does not.
The checklist applies to every release notes setup, from a single CHANGELOG.md in a Git repo through a CCMS-driven multi-channel pipeline. Audience count and channel count set the threshold for tooling complexity. The feature list does not.
Where Topicary fits
Topicary is a cloud-native CCMS designed for documentation teams of 2 to 15 writers. For release notes, conditional content produces developer and customer outputs from one source release note. Variables hold version numbers as named tokens that update across every release entry that references them. Reusable components manage boilerplate migration steps and known-issue templates centrally. Multi-channel publishing sends one source to a web docs site, a PDF for compliance, and Markdown for the GitHub CHANGELOG. Token-based reviewer access lets SMEs approve release notes before publication without needing login accounts.
A team shipping a single open-source library with one audience does not need any of this. A CHANGELOG.md following the Keep a Changelog spec is the right tool. Reading documentation version control patterns will get you further than adopting a CCMS. The crossover comes when developer and customer audiences read in different channels. Or when the same release note ships as in-app widget plus email plus PDF. Or when the team is maintaining the same migration paragraph in 6 places. At that point structured content patterns for consistent release notes reduce the maintenance budget by an order of magnitude. The broader picture of how this fits into a documentation toolchain is in the comparison of technical writing software for teams.
Frequently asked questions
What is a release notes template?
A release notes template is a fixed structure for documenting a software release. It covers version, date, summary, new features, improvements, bug fixes, breaking changes, migration steps, deprecations, and known issues. The structure is what lets readers scan a release in 30 seconds and find the part that matters to them. Without a template, every release reads differently and readers stop trusting the document.
What sections should release notes include?
Ten sections at most. The header carries version, date, status, and audience. Then come a summary, new features, improvements, bug fixes, breaking changes, migration steps, deprecations, and known issues. The last section links to the previous release. The Keep a Changelog 1.1.0 specification collapses these into six categories (Added, Changed, Deprecated, Removed, Fixed, Security). That works well for library changelogs. It is too thin for SaaS products that need migration steps and customer-facing summaries.
What is the difference between release notes and a changelog?
Release notes are scoped to a single versioned release and address both developers and customers, routinely including migration steps and known issues. A changelog is a rolling list of every change across all versions, typically terse and developer-oriented. A what's new page is a curated, narrative summary aimed at end users. The same team frequently publishes all three from the same source content.
How frequently should release notes be published?
Publish on every release that ships user-visible change. For a library on semantic versioning that is every MAJOR, MINOR, or PATCH bump. For a SaaS product on continuous deployment it is usually a weekly or monthly digest, with same-day notes only for breaking changes and security fixes. The rule that holds across both: never let a breaking change ship without release notes that name it.
Should release notes be auto-generated from commit messages?
It depends on who reads them. Take an internal-only API or a developer-tool library where every consumer also writes Conventional Commits. There, an auto-generated changelog from the commit log is acceptable and saves time. For anything customer-facing, auto-generation fails — commit messages are written by engineers for engineers and miss the audience, the migration steps, and the breaking-change framing. The compromise that works is auto-generated as the first draft and human-edited before publication.
Where should release notes live?
Wherever the audience already looks. For developers that means the docs site, the API reference, and a CHANGELOG.md in the repository. For customers that means the product itself (in-app changelog widget), the help center, and the email digest. The structural decision is to write the release note once and publish it to those surfaces — anything else turns into three documents that drift apart.
Sources
- Keep a Changelog 1.1.0. Olivier Lacan, 2022. https://keepachangelog.com/en/1.1.0/
- Semantic Versioning 2.0.0. Tom Preston-Werner, 2013. https://semver.org/
- Calendar Versioning. Mahmoud Hashemi and contributors, 2024. https://calver.org/
- Stripe API changelog. Stripe, 2026. https://docs.stripe.com/changelog
- Linear changelog. Linear, 2026. https://linear.app/changelog
- Kubernetes release notes. Kubernetes project, 2026. https://kubernetes.io/docs/setup/release/notes/
- ISO 8601:2019 — Date and time representations for information interchange. International Organization for Standardization, 2019. https://www.iso.org/standard/70907.html