How to Write Technical Release Notes

Learn how to write clear technical release notes: breaking changes, added/changed/fixed/removed sections, versioning, audience, and examples from Stripe and GitHub.

Release notes are often the first thing a developer reads after a software update. They communicate what changed, what broke, what was fixed, and what new capabilities are available. Written well, release notes build trust and reduce support burden. Written poorly, they generate confusion, missed migrations, and angry developers. This guide explains how to write excellent technical release notes in English.


Know Your Audience

Before you write a single word, identify who will read your release notes.

  • SDK users need to know about API changes that affect their code.
  • Platform operators need to know about infrastructure or configuration changes.
  • End users need to understand changes in terms of features and behaviour, not implementation details.

Most technical release notes target developers integrating with an API or maintaining a dependency. Write for that audience: precise, specific, and respectful of their time.


The Keep a Changelog Format

The Keep a Changelog format is the most widely adopted standard for technical release notes. It organises changes into labelled sections:

  • Added — new features
  • Changed — changes to existing functionality
  • Deprecated — features that will be removed in a future release
  • Removed — features removed in this release
  • Fixed — bug fixes
  • Security — vulnerability fixes

Example from Stripe-style release notes:

Added

  • Added PaymentIntent.capture_method support for split capture flows.
  • The charges endpoint now accepts metadata arrays of up to 50 key-value pairs (previously 20).

Changed

  • Invoice.due_date now defaults to null when no due date is set, rather than returning the creation date.

Fixed

  • Fixed an issue where webhook retries could trigger duplicate payment_intent.succeeded events in edge cases involving network timeouts.

Removed

  • Removed the source field from PaymentIntent objects. Use payment_method instead.

Breaking Changes — Handle with Care

Breaking changes are the most critical thing to communicate. A breaking change is any change that requires existing consumers to modify their code to continue functioning correctly.

Always:

  • Call out breaking changes at the top of the release notes or in a dedicated section
  • Explain exactly what changed and what the developer must do
  • Provide a migration path or link to a migration guide
  • Give advance warning in the previous release (deprecation) whenever possible

Breaking change: The user.get() method no longer accepts positional arguments. Update all calls from user.get(userId) to user.get(id=userId). Positional argument support was deprecated in v2.4 and has been removed in v3.0.”


Versioning Context

State clearly which version the notes apply to, and reference the previous version so developers understand the delta.

“Version 4.2.0 — released 2026-06-14 (previous: 4.1.3)”

Follow Semantic Versioning (SemVer) conventions:

  • Major (4.0.0) — breaking changes
  • Minor (4.2.0) — new features, backwards compatible
  • Patch (4.2.1) — bug fixes, backwards compatible

If your release increments the major version, the developer’s first question will be “what broke?” — answer it prominently.


What Good Release Notes Look Like: Real Examples

GitHub’s style is concise and action-oriented:

“Dependabot alerts now include the CVSS score and severity rating for each vulnerability, making it easier to prioritise remediation.”

Stripe’s style is precise and developer-focused:

“Added confirm parameter to PaymentIntent.create. When confirm=true, the intent is confirmed immediately, saving an extra API call for synchronous payment flows.”

Both examples share common traits:

  • One clear sentence per change
  • Specific, not vague (“easier to prioritise remediation”, not “improved”)
  • Developer context included (why this change matters)

What to Avoid

Vague descriptions:

Poor: “Improved performance.” Better: “Reduced average response time for the /search endpoint from 420 ms to 85 ms under typical query loads.”

Developer jargon without explanation:

Poor: “Refactored the connection pool to use epoll.” Better: “Improved connection handling under high concurrency — the server now handles 3x more simultaneous connections before performance degrades.”

Missing migration information for breaking changes:

Poor: “Removed the legacy authentication method.” Better: “Removed the legacy api_key query parameter authentication method. Migrate to Authorization: Bearer <token> header authentication. See the [migration guide] for details.”


Practical Phrases for Release Notes

  • “This release contains a breaking change to…”
  • “Developers using X should update to Y before upgrading.”
  • “This feature was deprecated in v2.1 and has now been removed.”
  • “Fixed an issue where… which caused… under…”
  • “Added support for… previously it was necessary to…”
  • “No action is required for existing integrations.”
  • “This change is backwards compatible.”

Good release notes are a form of respect for your users. They demonstrate that you understand the impact of your changes on real codebases and that you value your developers’ time. Invest in writing them well — they reduce support tickets, reduce upgrade friction, and build the kind of developer trust that drives long-term adoption.