# RFC: A new versioning strategy for Discourse

**URL:** https://meta.discourse.org/t/rfc-a-new-versioning-strategy-for-discourse/383536
**Category:** Development
**Tags:** dev-news
**Created:** [September 23, 2025, 7:55am UTC](https://meta.discourse.org/t/rfc-a-new-versioning-strategy-for-discourse/383536 "2025-09-23T07:55:33Z")
**Posts on this page:** 1
**Showing post:** 1

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [September 23, 2025, 7:55am UTC](https://meta.discourse.org/t/rfc-a-new-versioning-strategy-for-discourse/383536/1 "2025-09-23T07:55:33Z")

</div>

We’re planning to introduce a new versioning system for Discourse. Our goal is to provide more choice & predictability for community administrators, while maintaining our development velocity. We’re also adjusting some terminology to align better with other software.

This document will evolve as we receive comments, begin to implement the system, and then expand use of the new release streams.

If you have any comments/suggestions at this stage, please let us know by replying to this topic!

* * *

## Goals

1. Introduce more regular ‘releases’ for Discourse, which provide a balance between speed-of-development and stability

2. Continue to provide approx. 6-monthly releases which are supported for an extended period

3. Provide overlapping support for regular & extended-support releases, so that administrators have more flexibility over update timing, while continuing to receive critical security updates

4. Keep ceremony around ‘releases’ to a bare minimum. As much as possible should be automated, and should not slow down the core developer experience. ESR releases are just the same as any other release.

5. Naming & procedure should match industry standards, so that it’s easier to explain to developers & end-users

## High-level Overview

- Cut approximately one release per month. The ‘major’ version is the current year, and the ‘minor’ version increments with each release. The patch version number will be incremented for any backported fixes

- Approximately every 6 months, declare one of those releases as an Extended Support Release (ESR). ESR versions remain supported for 2 releases after the next ESR is declared.

- Provide critical fixes for `latest`, the most recent release, the previous release, and any active ESR versions.

- Rename the `tests-passed` branch to `latest`

Example graph of support periods over a year:

```mermaid
gantt
    title Discourse Releases and Support Periods (Jan 2026 – Jan 2027)
    dateFormat YYYY-MM-DD
    axisFormat %b %Y

    2026.0 (ESR) :active, 2026-01-27, 2026-09-29
    2026.1 :done, 2026-02-24, 2026-04-28
    2026.2 :done, 2026-03-31, 2026-05-26
    2026.3 :done, 2026-04-28, 2026-06-30
    2026.4 :done, 2026-05-26, 2026-07-28
    2026.5 :done, 2026-06-30, 2026-08-25
    2026.6 (ESR) :active, 2026-07-28, 2027-01-26
    2026.7 :done, 2026-08-25, 2026-10-27
    2026.8 :done, 2026-09-29, 2026-11-24
    2026.9 :done, 2026-10-27, 2026-12-29
    2026.10 :done, 2026-11-24, 2027-01-26
    2026.11 :done, 2026-12-29, 2027-01-26

```

## Implementation

- Each release will have a branch cut from `latest`. These will be namespaced, and preserved indefinitely. For example, `v2026.1` would have a branch named `release/2026.1`

- Each patch release will be tagged. e.g. `v2026.1.0`, `v2026.1.1`, etc.

- The latest release will be tagged `release`. The latest ESR will be tagged `esr`.

- Previous release will be tagged `release-previous`. Previous active ESR (if any) will be tagged `esr-previous`.

- For backwards compatibility, tags matching the existing release streams will be aliased to the closest new equivalent. `stable` → `esr`. `beta` → `release`. `tests-passed` → `latest`.

- On `latest`, the version number will be the currently-in-development version, suffixed with `-latest`. e.g. `2026.3.0-latest`

## Automated Release Process

Each month, a GitHub action will open a new PR containing a single commit which bumps the `version.rb` on `main` to the next `-latest` version.

Once a human has merged the PR, another GitHub action will detect `main` moving to the next `-latest` and cut a branch for the completed release. Essentially, this branch becomes a ‘release candidate’. Another automated PR will be opened against the release branch with an update to remove the `-latest` suffix from `version.rb`, and thereby ‘release’ it.

Usually, we’ll merge these two PRs in quick succession. But having separate PRs for creating and finalizing the release gives us the option to address any issues in the branch prior to finalizing.

```mermaid
    %%{init: { 'logLevel': 'debug', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchOrder': 2}} }%%
    gitGraph
       checkout main
       commit id:'version v2026.1-latest'
       commit id:'...'
       commit id:'....'
       branch 'release/2026.1'
       commit id:'version 2026.1'
       checkout 'main'
       commit id:'version v2026.2-latest'

```

Separately, another GitHub actions workflow will watch for any backported commits to release branches. When any are found, a new PR will be generated to bump the patch version on that branch. A human can decide when to merge those PRs.

All these automations will automatically keep various tags (`release`, `release-previous`, `esr`, `esr-previous`, plus backwards-compatibility aliases) up-to-date.

## Security Fixes

Security fix workflow remains largely the same, except that we now need to make the fixes in two of these three new places:

- `latest`

- `esr`

- `esr-previous` 🆕

- `release` 🆕

- `release-previous` 🆕

(Remember, per the earlier illustration, it’s only two of the three because `esr-previous` is supported, the new `esr` is the same as `release` or `release-previous`, and we drop support for `esr-previous` when that’s no longer true).

When introducing a security fix to `latest`, a `latest-security-fix` tag will automatically be moved to that commit. docker\_manager will be updated to monitor that tag and prompt admins to update. This allows us to release and notify about security fixes without needing to expedite a version bump.

## Translations

At the moment, the `stable` and `tests-passed` branches can be translated in CrowdIn, and the results are regularly integrated. In the new system, we initially plan for `latest` and `release` to be translatable in CrowdIn.

Ideally, by the time `release` becomes `release-previous` or `esr`, translations will have settled. If there is demand for continuous translations of those versions, then that’s something which could be considered in future.

## Plugin/Theme Compatibility

Increasing the use of non-`latest` streams of Discourse will increase our dependence on the `discourse-compatibility` system. So we need some improvements to the compat system.

Instead of using a `.discourse-compatibility` file on `main`, we could instead support implicit compatibility based on specially-named branches/tags. This should be much easier than juggling commit hashes manually. For example, a plugin could have branches like

- `d-compat/v2026.1`
- `d-compat/v2026.2`
- `d-compat/v2026.3`
- `main` (used for any Discourse version which doesn’t have its own branch)

When installing a plugin, Discourse can check for a branch matching the current version. If it exists, check that out. Otherwise, check the `.discourse-compatibility` file. Otherwise, check out the default branch.

We can create a public GitHub action which runs on each theme/plugin daily, checks for new Discourse releases, and automatically creates these branches. Each theme/plugin could choose to use this auto-pinning action, or they could go for a more ‘floating’ strategy.

## `discourse.org` hosting

Initially, our hosted offering will continue to run the `latest` version of Discourse. In the future, we’ll be exploring options for our enterprise-tier customers to select a ‘release’ version.

## [Standard install](https://meta.discourse.org/t/142537?silent=true) defaults

Initially, the default will remain `latest`. Admins will be able to opt-in to the new release stream in the same way that they opt-in to stable at the moment. We may explore easier switches between release streams in future, once the system is more mature.

---

_[View the full topic](https://meta.discourse.org/t/rfc-a-new-versioning-strategy-for-discourse/383536)._
