What Should Actually Be in a Software Changelog


Most changelogs are useless. They fall into one of two traps: either they are so sparse that they read like a marketing brochure ("Bug fixes and performance improvements!"), or they are so bloated with raw commit messages that they are illegible to anyone who didn't write the code.
The reader — whether an end user, an API consumer, or an internal stakeholder — wants the Goldilocks version. Comprehensive enough to be actionable, focused enough to be readable. They want to know what changed, why it matters, and what they need to do about it.
This isn't a philosophical debate about the nature of software evolution. It's a practical guide to the taxonomy of a changelog: what goes in, what stays out, and how to structure it so people actually read it.
The Core Taxonomy
A standard, effective changelog relies on a strict taxonomy. The Keep a Changelog specification provides the canonical foundation, which maps cleanly to Semantic Versioning and Conventional Commits. The six categories are not arbitrary — each one carries a different level of urgency and requires a different level of detail.
New Features (Added)
This category is for entirely new functionality. The granularity depends on the audience. For an API consumer, a new endpoint or a new parameter on an existing endpoint is a feature. For an end user of a SaaS application, a new button or a new workflow is a feature.
Include the name of the feature, a brief explanation of its value, and a link to the relevant documentation. Exclude the internal architectural changes required to support the feature. Users don't care that you migrated to a new database to make the feature work; they care that they can now export their data to CSV.
Improvements and Enhancements (Changed)
This is where things get murky. An enhancement is a change to existing functionality. It is not a bug fix (the feature was working as designed, but now it works better), and it is not a new feature (the core capability already existed).
Include what the behavior was before, what it is now, and why it's better. For example: "The search bar now supports fuzzy matching, improving results for misspelled queries." Exclude refactoring that doesn't change the user experience. If you rewrote the search algorithm to be 10% faster but the UI and the results are identical, that's an internal detail, not a changelog entry.
Bug Fixes (Fixed)
Include fixes for bugs that users actually encountered or reported. Describe the symptom, not the code change. "Fixed an issue where the 'Save' button was unresponsive on mobile devices" is good. "Fixed a null pointer exception in the SaveController" is bad. Exclude fixes for bugs that were introduced and resolved within the same development cycle — bugs that never made it to production. Minor visual glitches that don't impact usability can often be grouped into a single "Minor UI fixes" bullet point.
Deprecations and Removals (Deprecated / Removed)
These categories require special treatment because they represent a loss of functionality or a required action from the user. A deprecation is a warning that a feature will be removed in the future; a removal is the actual deletion of the feature.
Include a clear timeline for when the deprecated feature will be removed, and a migration path or alternative solution. When the feature is finally removed, state it plainly. Do not bury deprecations at the bottom of the changelog. They should be highly visible. As Keep a Changelog puts it: "It should be possible to upgrade to a version that lists deprecations, remove what's deprecated, then upgrade to the version where the deprecations become removals."
Breaking Changes
This is the most critical section of any changelog. A breaking change is any modification that requires the user to update their integration or change their workflow to maintain current functionality. In Semantic Versioning, this triggers a Major version bump.
Include a prominent warning, a detailed explanation of what broke, and a step-by-step migration guide. GitLab's approach to breaking changes is a useful model: they require leadership sign-off for breaking changes and provide extensive documentation on how to adapt. Nothing should be excluded here. If it breaks the user's workflow, it must be documented.
Security Updates (Security)
Security updates are a delicate balancing act between transparency and risk mitigation.
Include the nature of the vulnerability, the impact, and the resolution. If a CVE (Common Vulnerabilities and Exposures) identifier has been assigned, include the CVE number. As Cloudflare notes in their vulnerability disclosure policy, transparency builds trust. Exclude exploit details. Do not provide a roadmap for how to exploit the vulnerability, especially if a significant portion of your user base has not yet patched.
Audience Segmentation
One of the most common questions in changelog management is whether to maintain different changelogs for different audiences. The short answer is yes, but with a caveat: maintain a single source of truth and generate audience-specific views from it.
As highlighted by Appcues, there is a distinct difference between a technical changelog and user-facing release notes. The table below captures the key distinctions:
Maintaining these separately by hand is a recipe for maintenance hell. The practical solution is to use the engineering changelog — driven by commits and pull requests — as the foundational database. From there, product marketing can extract and elevate the items that matter to end users into release notes, while the raw technical changelog remains available for developers.
Version Numbering and What It Signals
If you are building an API, an SDK, or a library, Semantic Versioning (SemVer) is non-negotiable. It provides a universal language for communicating the impact of a release.
MAJOR (X.y.z) signals incompatible API changes — i.e., Breaking Changes. MINOR (x.Y.z) signals backward-compatible new functionality, including deprecations. PATCH (x.y.Z) signals backward-compatible bug fixes and security patches.
The changelog should be organized by these version numbers, with the most recent release at the top. Each version header should include the release date in an unambiguous format (YYYY-MM-DD, per the ISO 8601 standard).
The Abstraction Gap Between Commits and Changelogs
The biggest mistake engineering teams make is assuming that a list of commit messages is a changelog. It is not.
A commit message explains how the code changed. A changelog entry explains why the user should care. This is the abstraction gap. An empirical study on software release notes [7] found that 47% of release artifacts lacked traceability links to the underlying commits or pull requests — a disconnect that makes it difficult to verify what actually shipped.
To bridge this gap, teams must enforce a structured commit convention, such as Conventional Commits. When engineers prefix their commits with feat:, fix:, or BREAKING CHANGE:, it provides the metadata necessary to automatically categorize the changes. However, the commit message itself still needs to be translated into user-centric language before it appears in a public changelog.
Tone and Voice
Changelogs are often the first place users look when something breaks. They are frustrated, confused, and looking for answers.
The tone should be objective, precise, and devoid of marketing fluff. Do not try to be funny. Do not try to sell the user on the feature. Just tell them what changed.
Should you write for your least technical user or your most technical one? The answer depends on the product. If you are building a developer tool like Stripe [8], write for the most technical user. If you are building a consumer app, write for the least technical user. If you have a mixed audience, use the segmentation strategy above: technical precision in the changelog, accessible benefits in the release notes.
The WorkOS changelog [9] captures this well: "A changelog isn't a place to sell. The content must be essential, straightforward, and clear. If you have fluff in your changelog, you're doing it wrong."
Tooling and Automation
Manual changelog compilation is a soul-crushing task that usually happens at the last minute before a release. It is prone to errors and omissions.
The modern workflow relies on automation, but automation with editorial control. Tools like git-cliff [10] can parse Conventional Commits and generate a structured Markdown file. The ideal workflow looks like this:
- Engineers write structured commit messages (feat:, fix:).
- Pull requests require a user-facing description of the change.
- During the release process, an automated tool aggregates the PR descriptions — not the raw commits — into a draft changelog.
- A human (usually a PM or technical writer) reviews, edits, and approves the draft before it is published.
This ensures that the changelog is comprehensive because it's driven by the code, but readable because it's reviewed by a human.
Generating clear, well-structured release notes and changelogs from engineering workflows is exactly what Doc Holiday automates. It takes commit messages, pull request descriptions, and issue tracker updates and produces categorized, readable changelog entries. The system gives teams a validation layer to review and approve output before it ships, so you get the speed of automation with the quality control of human oversight.

