Skip to main content

Release Versioning and Release Notes

Version releases meaningfully; communicate changes clearly to stakeholders.

TL;DR

Semantic Versioning (semver): MAJOR.MINOR.PATCH. MAJOR increments for breaking changes (v1.0 → v2.0), MINOR for backward-compatible features (v1.0 → v1.1), PATCH for bug fixes (v1.0 → v1.0.1). This simple scheme tells users at a glance whether they can upgrade safely.

Release notes communicate what changed and why it matters. Include: version number and date, new features (with impact), bug fixes (critical ones highlighted), breaking changes (with migration guide), deprecations (with timelines), known issues, security notes. Write for your audience: customers care about business impact, ops teams care about deployment notes, product cares about features shipped.

Automation: Generate release notes from commit messages using tools like Conventional Commits. This ensures consistent, automated release documentation.

Learning Objectives

  • Design a clear versioning strategy
  • Communicate releases effectively to different stakeholders
  • Document breaking changes and migration paths
  • Deprecate safely with advance notice
  • Automate release note generation
  • Track and report on release quality

Motivating Scenario

Your company publishes a widely-used API library. Three months ago, you released version 2.0 with a breaking API change. The release notes said "See migration guide." But customers had to search your wiki to find it—it was 6 clicks away. One customer didn't find it and their application broke in production. Another customer saw "2.0.1" released a week later but had no idea if they should upgrade. Was it security critical? A bugfix? A new feature they didn't need?

You need a clear versioning scheme and release communication that tells users exactly what they need to know.

Core Concepts

Semantic Versioning (SemVer)

Semantic Versioning is a simple, machine-readable scheme: MAJOR.MINOR.PATCH.

MAJOR (Breaking changes):

  • Increment when you change the API in an incompatible way
  • v1.0.0 → v2.0.0
  • Example: Removing a function, changing a function signature, changing behavior
  • Users must read migration guide and potentially modify code

MINOR (New features, backward compatible):

  • Increment when you add functionality that's backward compatible
  • v1.0.0 → v1.1.0
  • Example: Adding a new function, adding an optional parameter
  • Users can upgrade safely; old code still works

PATCH (Bug fixes):

  • Increment when you fix bugs without changing functionality
  • v1.0.0 → v1.0.1
  • Users should upgrade (bug fixes improve reliability)
Semantic Versioning Decision Tree

Pre-release versions: v1.0.0-beta.1, v1.0.0-rc.1. These are unstable; users shouldn't use in production.

Build metadata: v1.0.0+20250214. The part after + is metadata and doesn't affect version precedence.

Release Notes Structure

Effective release notes follow a consistent structure:

  1. Header: Version number, release date
  2. Breaking Changes (if any): Explain what changed and why; provide migration guide
  3. New Features: What can users do now? How does it improve their workflow?
  4. Bug Fixes: Critical ones highlighted
  5. Deprecations: What's being removed? When? What's the alternative?
  6. Known Issues: What doesn't work? When will it be fixed?
  7. Security: Any CVEs fixed? Upgrade urgency?
  8. Contributors: Who built this?

Audience-specific notes:

  • Customers: Focus on impact. "Authentication now works offline" (benefit-driven)
  • Operations: Focus on deployment. "Requires new environment variable: AUTH_ENDPOINT"
  • Product/Leadership: Focus on business value. "Shipped 3 requested features, 12 bug fixes, improved performance by 20%"

Versioning Schemes for Different Types of Software

TypeSchemeExampleNotes
Library/APISemVerv2.3.4Users depend on stable interface; breaking changes are critical
Web AppTime-based or continuous2025.02.14 or build #12345Users don't control upgrades; backward compatibility less critical
Operating SystemHybridUbuntu 22.04 LTSYear.month. LTS = long-term support
Data ServiceSchema version + releasedb_v5 + release 2.1.0Schema changes are breaking; must be managed carefully
Internal ServicesSimplifiedv1, v2If only used internally, simpler versioning acceptable

Deprecation Strategy

Deprecating features safely requires advance notice:

Phase 1 (Announcement): Release version 1.5, document deprecated feature

  • Example: "Function get_user() is deprecated; use get_user_v2() instead. Removing in v2.0."
  • Release notes: "Three functions deprecated. See migration guide for alternatives."

Phase 2 (Grace period): 2-4 releases (typically 3-6 months)

  • Feature still works but shows warnings in logs
  • Documentation updated to steer new users to replacement
  • Continue release notes reminding of upcoming removal

Phase 3 (Removal): Next major version

  • Example: v2.0 removes deprecated functions
  • Release notes have prominent section: "Breaking Changes" with migration guide

Automating Release Notes

Modern teams automate release notes from commit messages using Conventional Commits:

feat: add user authentication
fix: correct off-by-one error in pagination
docs: update API reference
perf: optimize database queries
BREAKING CHANGE: remove deprecated getUser() method

Tools parse these and generate release notes:

## v2.0.0 (2025-02-14)

### Breaking Changes
- Remove deprecated getUser() method (use getUserV2 instead)

### New Features
- Add user authentication system
- Add role-based access control

### Bug Fixes
- Fix off-by-one error in pagination
- Fix race condition in cache invalidation

### Performance
- Optimize database queries (40% faster)

### Contributors
- Alice (features), Bob (bugfixes), Carol (docs)

Practical Examples

Scenario 1: Bug fix
Current: v1.2.3
Fix: Database connection pooling bug
New version: v1.2.4

Scenario 2: New feature
Current: v1.2.4
Feature: Add webhook support
New version: v1.3.0 (users can upgrade safely)

Scenario 3: Breaking change
Current: v1.3.0
Change: Rename API endpoint /users → /api/v1/users
New version: v2.0.0 (migration required)

Scenario 4: Pre-release
Feature branch: v2.0.0-beta.1
For early testing by interested users

Scenario 5: Multiple pre-releases
Beta testing: v2.0.0-beta.1, v2.0.0-beta.2, v2.0.0-beta.3
Release candidate: v2.0.0-rc.1
Stable: v2.0.0

When to Use / When Not to Use

Use Semantic Versioning When:
  1. You publish a library, SDK, or API that external users depend on
  2. Breaking changes require customer migration
  3. You need users to understand upgrade safety at a glance
  4. You have multiple releases per month
  5. Compatibility matters to your business
Use Time-Based or Continuous Versioning When:
  1. You run a web app with continuous deployment (internal or users don't control upgrades)
  2. Breaking changes don't affect external users
  3. Version number is less important than feature flags for managing rollouts
  4. You deploy multiple times per day

Patterns and Pitfalls

Patterns and Pitfalls

Anti-pattern: Release notes with only technical jargon: 'Refactored auth handler. Updated deps. Fixed race condition.' Users don't know if they need to upgrade or what changed. Better: 'Fixed critical authentication bug (could allow access without proper credentials). Upgrade immediately. No code changes required.' Include impact and migration steps.
Anti-pattern: MAJOR version bump with no explanation of what changed or how to migrate. Users are angry. Better: Prominent section in release notes with before/after code examples. Link to detailed migration guide. Explain why the change was necessary.
Anti-pattern: 'Function X is deprecated and will be removed.' When? Users don't know if they have 1 month or 2 years. Better: 'Function X deprecated in v1.5, will be removed in v3.0 (expected Q3 2025). Use Y instead.' Clear timeline.
Anti-pattern: Just a version number and commit messages. Users don't know what's new. Better: Even short release notes help. At minimum: new features, bug fixes, breaking changes. Automate from conventional commits if manual writing is too much overhead.
Anti-pattern: Same release notes for customers, ops, and developers. Customers don't care about internal refactoring; ops doesn't care about new features. Better: Tailor release notes. Customer-facing: business impact. Ops: deployment requirements and config changes. Developers: API changes and deprecations.
Anti-pattern: Using SemVer but not being consistent about what breaks. MAJOR bumps from v1 to v2 for minor changes, then keep v2.x for major changes. Users can't trust the version number. Better: Strict adherence to SemVer rules. If in doubt, bump MAJOR.

Design Review Checklist

  • Do you use Semantic Versioning or a documented versioning scheme?
  • Are release notes written and published for every release?
  • Do release notes include breaking changes and migration guides?
  • Are deprecations announced with clear timelines?
  • Can release notes be understood by non-technical stakeholders?
  • Is security information included in release notes?
  • Are release notes automated (from commits or conventional changelog)?
  • Do you have a CHANGELOG.md file in version control?
  • Are pre-release versions clearly marked and discouraged for production use?
  • Do you communicate major version deprecation at least 2 releases in advance?
  • Is there a process for communicating critical security releases immediately?
  • Do release notes link to migration guides for major changes?

Self-Check Questions

  1. Versioning Scheme: What's your versioning scheme? Can someone unfamiliar with your project understand the version number?
  2. Breaking Changes: How do you communicate breaking changes? Do users have time to plan migration?
  3. Deprecation Timeline: When you deprecate a feature, how much notice do users get? (Ideal: at least 2-3 releases)
  4. Automation: Are release notes generated automatically or written manually?
  5. Audience: Who reads your release notes? Do they contain information relevant to each audience?

Next Steps

  1. Adopt Semantic Versioning: If you're not already using it, switch now.
  2. Write Release Notes: For the next release, write comprehensive release notes.
  3. Automate: Set up conventional commits and automated release note generation.
  4. Deprecation Policy: Document how you deprecate features (timeline, notice period).
  5. Communicate: Share release notes proactively (email, RSS, Slack, docs).

References

  1. Semantic Versioning ↗️
  2. Keep a Changelog ↗️
  3. Conventional Commits ↗️
  4. Humble, J., & Farley, D. (2010). Continuous Delivery. Addison-Wesley.
  5. Semantic Release (GitHub) ↗️