How to write a changelog people actually read
A good changelog is one of the cheapest trust-building tools a small software team has, and one of the most commonly neglected. Here's what we've found actually makes one worth reading — regardless of what tool, if any, you use to publish it.
Write it for the person using the product, not the person who built it
A commit message and a changelog entry answer different questions. The commit message answers "what did I change in the code?" The changelog entry answers "what does this mean for me?" Those are rarely the same sentence.
Commit: fix: guard null in useAuth hook on token refresh
Changelog: "Fixed a bug where you could get logged out unexpectedly
while your session was refreshing."
The second version doesn't mention the hook, the function, or the file. It says what the customer experienced, and that it's fixed. That's the whole translation job, every time: strip out the implementation, keep the effect.
One entry, one change
Resist folding three unrelated fixes into one bullet just because they merged in the same pull request. If a customer could notice change A without noticing change B, they're two entries. Bundling them saves you a line of writing and costs the reader the ability to scan for the one thing they care about.
Categorise consistently
Pick a small, stable set of categories and use them release after release. A common set, close to the widely-used Keep a Changelog convention:
- Added — a new feature or capability.
- Changed — existing behaviour that's different now.
- Fixed — a bug that's gone.
- Removed — something that used to exist and doesn't any more.
- Breaking — anything that could break an integration or workflow if the reader doesn't act on it.
Consistency matters more than the exact label set you pick. A reader who's skimmed your last five releases should be able to guess where a given change will show up before they read it.
Breaking changes get more attention, not less
The instinct is to soften a breaking change because it's the one piece of bad news in the release. Do the opposite: state plainly what breaks, by when, and what the reader needs to do about it.
Weak: "We've made some improvements to our webhook security." Better: "Webhooks now need a signed secret. Existing integrations keep working until 1 September. After that date, unsigned webhooks are rejected. Migration guide: [link]."
The second version gives the reader everything they need to act, in one sentence. Nobody has ever complained that a changelog was too clear about a deadline.
Say what changed, not that you're excited about it
"We're thrilled to announce our brand-new dashboard!" tells the reader nothing about the dashboard. "The dashboard now loads your last 30 days of activity by default, instead of asking for a date range every time" tells them exactly what's different and why it matters. Enthusiasm belongs in how often you ship, not in how loudly you describe each entry.
Leave out what the customer can't observe
Refactors, dependency bumps, internal tooling changes, test coverage — all real work, none of it belongs in a customer-facing changelog unless it changed something the customer can see, feel, or measure (a page that used to be slow and now isn't, say). If in doubt, ask: would a customer notice this without reading the changelog? If the honest answer is no, it isn't an entry.
Ship notes on the same rhythm you ship code
A changelog updated once a quarter reads like an afterthought no matter how well each entry is written. The value compounds with frequency — readers build a habit of checking, and "is this thing still being worked on?" stops being a question anyone asks. If you release weekly, publish weekly, even if some weeks are just a line or two.
A minimal entry template
## [Feature / Fix / Improvement / Breaking] — one-line summary
What changed, in plain language, from the reader's point of view.
If it's breaking: what they need to do, and by when.
That's the whole shape. Most of what makes a changelog worth reading is discipline in applying it consistently, not cleverness in any single entry.
We build ChangelogPilot because we'd rather teams spend their attention on the judgement calls above — what's worth mentioning, how serious a breaking change really is — than on the twenty minutes of remembering and typing that usually stands between a merged PR and a published entry. If that's a problem you recognise, see how it works. If it isn't, the guidance above holds regardless of what you publish with.