Release notes templates: 8 copy-paste formats for teams that ship from GitHub
Eight release notes templates in plain Markdown, each one filled in as a worked example: a standard software release, a minimal patch note, a user-facing product update, an API release with breaking changes, an app store submission, an internal deployment note, a sprint release, and an open-source GitHub release body.
What this solves
Someone has a release to ship and wants a copy-pasteable release notes document template that fits their audience, plus enough guidance to fill it in without rewriting the structure every time.
How S2P helps
Eight worked templates for release notes you can paste and edit today, a table that tells you which one your release needs, and the four rules that decide whether anyone reads the result.
Key takeaways
- A release notes template is a document skeleton written per version, and the whole value comes from the heading set never changing between releases.
- Semantic Versioning 2.0.0 defines the release type your first line should state: MAJOR for incompatible API changes, MINOR for backward compatible functionality, PATCH for backward compatible bug fixes.
- Apple limits the App Store 'What's New in This Version' field to 4000 characters and Google Play limits release notes to 500 Unicode characters per language, so store releases need their own shorter template.
- Jira can generate a first draft from the work items assigned to a version, in Jira itself or as a Confluence draft page, but it produces issue keys and summaries rather than impact.
- Generators can write the merged pull request list and the compare link; the summary, the migration steps and the upgrade command are always hand-written, which is exactly what the template is for.
Section 1
Start here: the standard software release notes template
Eight release notes examples follow, each one a filled-in template rather than a blank form. This is the one that fits most tagged releases.
A release notes document template is a skeleton you fill in once per version. The heading set never changes; only the lines under it do. That is the point: a reader who learns the shape once can scan it in five seconds every release, and scanning is the only way a release note gets read twice.
The version line does more work than it looks like. Semantic Versioning 2.0.0 states the contract precisely: increment MAJOR when you make incompatible API changes, MINOR when you add functionality in a backward compatible manner, and PATCH when you make backward compatible bug fixes. Putting the release type on line two tells a reader whether to keep reading before they read anything else.
The change headings use the vocabulary Keep a Changelog standardized, which lists its types of changes as Added, Changed, Deprecated, Removed, Fixed and Security. Use those words rather than inventing a set, because most of your readers already know what belongs under each one.
Which release notes template to use
| Template | Who reads it | When it wins | Length target |
|---|---|---|---|
| Standard software release | Users and integrators of your package | Any tagged MINOR or MAJOR release | 200 to 600 words |
| Minimal patch note | Existing users deciding whether to upgrade now | PATCH releases with backward compatible fixes only | Under 100 words |
| User-facing product update | Non-technical customers of a hosted product | Nobody installs anything, so the version is not the story | 150 to 300 words |
| API release with breaking changes | Developers who call your API in production | Any MAJOR bump, removed field or renamed value | 400 to 1000 words |
| Mobile app store release | App Store and Google Play visitors | Every store submission after the first one | 4000 characters on iOS, 500 on Android |
| Internal deployment note | On-call, support and the deploying team | Every production deploy, including config-only changes | Under 200 words |
| Sprint or agile release | Stakeholders, support and QA | A sprint boundary where scope moved | 200 to 400 words |
| Open-source GitHub release body | Contributors and downstream maintainers | A tagged release in a public repository | 150 to 400 words |
RELEASE-NOTES-v1.4.0.md
# Release Notes - Acme CLI v1.4.0
**Release date:** 2026-08-28
**Release type:** MINOR (new functionality, backward compatible)
**Tag:** v1.4.0
**Full changelog:** v1.3.2...v1.4.0
## Summary
One or two sentences a non-author can understand: what this release is
for, and who should upgrade now rather than at their leisure.
## Breaking changes
None.
## Added
- `acme sync --watch` re-runs the sync when a tracked file changes. (#412)
- Config accepts a `retries` key. Defaults to 3. (#415)
## Changed
- Timeouts are measured per request instead of per command. (#418)
## Fixed
- Fixed a hang when the upstream returned 429 during a retry. (#421)
## Deprecated
- `--legacy-format` is deprecated and will be removed in v2.0.0.
Use `--format=json`.
## Known issues
- Windows paths containing spaces still require quoting. Tracking in #430.
## Upgrade
npm install acme-cli@1.4.0
No config or migration changes required.Section 2
The minimal patch release note
Most releases are patch releases, and a patch release does not deserve six headings.
Under Semantic Versioning a PATCH release contains backward compatible bug fixes only. If that is true, say so on the first line and let the reader stop reading. A four-line sample release note a maintainer will actually write beats a full template that gets skipped because it demands a summary paragraph for a one-character fix.
Two lines carry the weight: the upgrade command and the compare link. The cost of this format is that it assumes trust, so if your last three patch releases broke something, use the standard template until that stops being true.
Patch release note
# v1.3.2 - 2026-08-28
PATCH release. Backward compatible bug fixes only. Safe to take without
reading further.
### Fixed
- Retry loop no longer spins when the upstream returns 429. (#398)
- Config loader resolves relative paths from the project root again. (#401)
**Upgrade:** `npm install acme-cli@1.3.2`
**Full changelog:** v1.3.1...v1.3.2Section 3
The user-facing product release notes template
For a hosted product nobody installs anything, so the version number is not the story. The behaviour change is.
This is the product release notes template that goes in an in-app what's new panel, an email, or a public updates page. Drop the tag, the release type and the pull request numbers. Lead with what a person can now do that they could not do yesterday, and say where in the interface to find it.
Keep it to two or three items per update, one sentence on the change and one on why it matters. If you shipped eleven things, pick the three a customer would notice and leave the rest in the developer-facing note.
The cost of this format is precision. Anyone integrating against you cannot work from it, so if you have both audiences you publish both: this note for users, and one of the engineering templates for the people reading your API.
What's new (in-app or email)
# What's new - August 2026
### Saved filters
You can now save any filter set and reopen it from the sidebar. Saved
filters belong to the workspace, so your team sees the same views you do.
Where to find it: Filters > Save current view.
### Improvements
- The repository picker opens without a loading state on large workspaces.
- Exports keep the column order you set.
### Fixes
- Fixed the queue appearing empty after a token refresh.
- Fixed timestamps showing in UTC instead of your local time zone.
### Coming next
Per-channel preview. Only list this if it is already in progress.
Something broken? Reply to this note or write to support@example.com.Section 4
The API release template for breaking changes
When you break an API, the release note is the migration guide. Everything else in it is secondary.
Stripe's public API changelog shows the pattern worth copying. Entries are versioned by date and API version name, grouped under product headings such as Billing and invoicing or Payments, and every entry carries an explicit Breaking change column marked Breaking or Non-breaking. The reader never has to infer whether a change affects them, which is the single most valuable property an API release note can have.
Semantic Versioning supplies the other half. Its own guidance on deprecation says that when you deprecate part of your public API you should update your documentation and issue a new minor release with the deprecation in place, keeping at least one minor release containing the deprecation before removing the functionality in a subsequent major release. So your Deprecated section names a removal version, not just the fact of deprecation.
Number the breaking changes and give each one a before, an after, a why and a migration. The numbering lets support write 'breaking change 2' in a ticket and lets you link a specific anchor from an error message.
API v3.0.0 release notes
# API v3.0.0 - breaking release
**Release date:** 2026-08-28
**Previous version:** v2.8.4
**Support window:** v2.x receives security fixes until 2027-02-28
## Breaking changes
| # | Change | Affected endpoint | Action required |
| --- | --- | --- | --- |
| 1 | `status` values renamed | `GET /v3/orders` | Map `queued` to `pending` |
| 2 | Field removed | `POST /v3/orders` | Stop sending `legacy_id` |
### 1. `status` values renamed
Before:
{"status": "queued"}
After:
{"status": "pending"}
Why: the old value did not distinguish accepted from in-flight.
Migration: treat any unknown status as `pending` for one release, then
switch to the new values.
### 2. `legacy_id` removed from the create payload
Requests that still send `legacy_id` return `400 invalid_request`.
Use `external_id`, which has accepted the same values since v2.6.0.
## Added
- `GET /v3/orders/{id}/events` returns the state transitions for one order.
## Deprecated (works in v3, removed in v4)
- `expand[]=customer`. Use the dedicated customer endpoint.
## How to pin
curl https://api.example.com/v3/orders \
-H "Authorization: Bearer $TOKEN" \
-H "X-Api-Version: 2026-08-28"Section 5
The mobile app release notes template
Application release notes for the two stores have hard limits, and the stores do not agree on them.
Apple's App Store Connect reference documents the What's New in This Version field as 'A description of the changes in this version of the app, such as new features, UI improvements, or bug fixes. Limited to 4000 characters.' Apple also states that the property is not available for the first version of an app but is required for all subsequent versions, and that it can be localized.
Google Play is far tighter. The Play Console help page on preparing and rolling out a release states that you can enter release notes using up to 500 Unicode characters per language, and that language tags go on separate lines from the notes, wrapping each translation in a tag such as en-US.
Write the Play version first, inside 500 characters, then expand it for Apple. Doing it the other way round means editing down under a character counter, per language, on submission day. App release notes are also the one place a support address earns its line.
App store release notes
# App Store - What's New in This Version (4000 characters maximum)
Saved filters are here, and cold start is faster on older devices.
NEW
- Saved filters: save any view and reopen it in one tap.
IMPROVED
- Faster cold start on older devices.
- Offline mode keeps your last 200 items instead of 50.
FIXED
- Fixed a crash when opening a shared link while signed out.
Trouble with this version? support@example.com. We answer.
# Google Play - Release notes (500 Unicode characters per language)
<en-US>
New: saved filters. Save any view and reopen it in one tap.
Improved: faster cold start, larger offline cache.
Fixed: crash when opening a shared link while signed out.
</en-US>Section 6
The internal deployment release notes template
A deployment note is not written for users. It is written for whoever gets paged in two hours.
This deployment release notes template lives in a deploy channel, a deploy tool, or a wiki page, and it answers three questions: what changed, what could break, and how to undo it. If a reader can find the rollback command in under five seconds, the template is doing its job.
Include the commit hash as well as the version. During an incident the person reading this is trying to diff two points in git history, and a tag is one lookup away from useful while the commit is zero. The feature flag line matters for the same reason: a change behind a flag at 10 percent is a different incident from the same change at 100 percent.
The cost is that this gets written at deploy time, when everyone wants to go home. Keep it short enough that filling it in is faster than arguing about whether to fill it in.
Deploy note
# Deploy note - orders-api - 2026-08-28 14:20 UTC
**Environment:** production
**Release:** v1.4.0 (commit 9f3c1ab)
**Deployed by:** @yourhandle
**Change type:** code (no schema change)
**Rollback:** `deploy rollback orders-api v1.3.2` - tested in staging: yes
## What shipped
- Per-request timeouts replace per-command timeouts. (#418)
- Retry loop no longer spins on 429. (#421)
## Risk and blast radius
- Affects: `POST /v3/orders` and the retry worker.
- Feature flags: `per_request_timeout` at 100 percent.
- Migrations: none.
- Backward compatible with the previous release: yes.
## Verification
- [ ] Health check green
- [ ] p95 latency within its normal range for 15 minutes
- [ ] Error rate unchanged for 15 minutes
## If it goes wrong
Roll back first, debug after. On-call rotation: #oncall-platform.Section 7
The sprint and agile release notes template
A sprint or project release note has one extra job: telling stakeholders what did not ship, and why.
Two columns do the work in this agile release notes template: the issue key and what a user notices. The key keeps it traceable back to the tracker, and the impact column forces a translation out of tracker language. A row whose impact reads 'nothing, internal only' is honest and useful, because it stops someone asking about it three weeks later.
Jira can generate the first draft. Atlassian's Jira Cloud documentation describes a release notes action on a version: open Releases, select the version, choose Release notes, pick your formatting options, then copy the result as markdown or HTML, or save it into the version's related work section. Atlassian notes one limitation, that notes containing panels, dates, expand sections or statuses cannot be copied as markdown. A Create in Confluence path produces a draft Confluence page prefilled from the version.
Jira Data Center works differently. Atlassian's admin documentation says the release notes contain all issues in the project marked with a specific Fix For version, and that the plain text and HTML layouts render from Velocity templates named releasenotes-text.vm and releasenotes-html.vm, which you can copy and customize. Either way the output is a list of issue keys and summaries: a starting point, with the impact column still yours to write.
Sprint release notes
# Sprint 42 release notes - Orders - 2026-08-28
**Version:** 2026.8.2
**Fix Version in Jira:** 2026.8.2
**Sprint goal:** cut checkout errors caused by upstream timeouts
## Delivered
| Key | Type | Summary | What a user notices |
| --- | --- | --- | --- |
| ORD-812 | Story | Per-request timeouts | Fewer failed checkouts on slow networks |
| ORD-830 | Bug | Retry loop on 429 | Orders stop duplicating |
| ORD-833 | Task | p95 latency dashboard | Nothing, internal only |
## Carried to sprint 43
| Key | Reason |
| --- | --- |
| ORD-844 | Blocked on the payments provider sandbox |
## Notes for support
- Duplicate orders created before this release still need manual merging.
Runbook: <link>
## Demo
Recording: <link>. Environment: staging.Section 8
The open-source GitHub release body template
A GitHub release body is read in three places: the releases page, the repository feed, and the notification email. Write it for the scan.
If you searched for a release notes template for GitHub, this is the one that goes in the release body itself. GitHub's own automatically generated notes produce a list of merged pull requests, a list of contributors to the release, and a link to a full changelog. This template keeps that shape and adds the two things no generator infers: a Breaking section pinned to the top, and an upgrade block containing the actual command.
Keep the per-line contributor attribution. It costs one line per entry and it is a meaningful part of why a first-time contributor opens a second pull request. Keep the compare link too, because anyone who wants the raw git history looks for it there first.
This is the release notes document, not the announcement. The post you write for LinkedIn, Discord or Hacker News about the same release is a different artifact with a different structure, and it is covered separately in our GitHub release announcement templates.
GitHub release body
## What's Changed
### Breaking
* Drop Node 18. Node 20 is now the minimum. by @maintainer in #512
### Added
* Add `--watch` to the sync command by @contributor in #498
### Fixed
* Fix hang on upstream 429 by @contributor in #505
## Upgrade
npm install acme-cli@2.0.0
Still on Node 18? Pin to `1.x` until you can move the runtime.
The 1.x line receives security fixes for six months.
## New Contributors
* @newperson made their first contribution in #498
**Full Changelog**: https://github.com/OWNER/REPO/compare/v1.9.3...v2.0.0Section 9
How to write release notes people actually read
The template gives you the shape. These rules decide whether anyone finishes reading it.
The most common failure is not length, it is abstraction. A line describing what you did to the code is worthless to a reader who has never seen the code. Rewrite it to start from something the reader observes, then attach the pull request number for anyone who wants the detail.
The second failure is 'various bug fixes and improvements'. It tells a reader nobody checked whether this release contained anything they care about, and after two or three of those they stop opening your notes.
A release notes format only pays off if it is the same one every release, so the file needs one canonical home. Keep it in the repository next to the code; pasting it into Word, Google Docs or a Confluence page for review is fine, because these headings survive a paste intact.
- Write the effect, not the implementation. The reader does not have your file tree.
- One change per line. If a line contains an 'and', it is two lines.
- Breaking changes go first, always, even when they are the smallest part of the release.
- Name the condition that triggered a bug. 'Fixed a crash' does not help anyone decide whether to upgrade.
- Delete anything with no observable effect. Dependency bumps and internal refactors belong behind the compare link, not in the note.
Rewriting three bad lines
Before:
- Refactored AuthProvider to use the new token exchange flow (#611)
After:
- Fixed: sessions no longer drop after 24 hours, so you are not signed
out every morning. (#611)
Before:
- Various bug fixes and improvements
After:
- Fixed: CSV export now includes rows created in the last hour.
- Fixed: the repository picker no longer hides repos you can only reach
through an organization.
Before:
- BREAKING: changed the status enum
After:
- Breaking: `status` now returns `pending` where it returned `queued`.
Map the old value for one release, then remove the mapping.Section 10
Automate the part that repeats
Half of a release note comes from your commit history and should never be typed by hand. The other half comes from your judgment and always will be.
Generators handle the mechanical half well: the merged pull request list, the contributor list, the compare link, and a version bump derived from commit messages or change files. Every practical way to do that on GitHub is covered in our guide to automating release notes on GitHub, linked below.
What no generator writes is the summary, the breaking-change migration, the known issues and the upgrade command. That is what the template is for: a fixed set of fields a human has to fill, in the same order every time, so filling them takes four minutes instead of forty.
The other repeating job starts after the note is published, when the same content gets rewritten by hand for every channel your team posts to. Ship 2 Post watches your repository through its GitHub App for releases, tags, merged pull requests and deployments, drafts channel-native variants in a brand voice you configure, and holds them in a review queue until you approve each one. It publishes to 14 destinations and keeps an audit trail back to the source signal. There is a free plan and no credit card.
FAQ
Questions this article answers
What is a good format for release notes?
A good format leads with the version number and release date, then a one-sentence summary, then changes grouped under stable headings: breaking changes first, then added, changed, fixed, deprecated and known issues. Close with the upgrade command and a compare link. Keep the heading set identical every release so readers learn to scan it rather than read it.
What should be included in release notes?
Version number, release date and release type; a summary a non-author can understand; breaking changes with their migration steps; new features; fixed bugs including the condition that triggered them; deprecations naming a removal version; known issues with workarounds; and the upgrade command. For a public API, add the support window for the previous version. For an app store, cut everything that is not user-visible.
How do you write release notes?
Write one line per change, describing the effect rather than the implementation, then attach the pull request number for anyone who wants detail. Say what changed, who it affects and what they must do. Replace 'refactored the auth provider' with 'sessions no longer drop after 24 hours'. Group the lines under fixed headings, put breaking changes at the top, and delete anything with no observable effect.
Can Jira generate release notes?
Yes. Atlassian's Jira Cloud documentation describes a release notes action on a version: open Releases, select the version, choose Release notes, pick formatting options, then copy the output as markdown or HTML or save it to the version's related work. A Create in Confluence path produces a prefilled draft page. Jira Data Center renders plain text or HTML from Velocity templates named releasenotes-text.vm and releasenotes-html.vm.
What are software release notes?
Software release notes are a per-version document telling readers what changed in one specific release and what they need to do about it: new features, changes, fixes, deprecations, breaking changes and known issues, scoped to that version alone. A changelog is the running file that accumulates every release over time, while release notes are the note that ships alongside a single version.
How to automate release notes?
Partly, and it is worth doing. GitHub's automatically generated release notes produce a list of merged pull requests, a list of contributors and a link to a full changelog, and other tools derive the same thing from git history or explicit change files. What no generator infers is the summary, the breaking-change migration or the upgrade command, which is why a template still earns its place alongside automation.
Related guides and pages
Where to go next
Hand-picked pages that go deeper on the workflow, channels, and tooling covered above.
