A small probe with antennae drifts through a violet and teal nebula toward a bright core, with a distant planet at the edge of the frame.
Guide

Release Candidate (RC): What It Means and How It Differs from Alpha, Beta, and GA

Felix Macx · · Updated · 10 min read

A release candidate (RC) is a build that will become the final release unless someone finds a serious bug in it. It’s feature-complete, it has passed the team’s own testing, and it’s published for one purpose: to give the wider world a last chance to prove it isn’t ready.

That’s the whole definition, and it’s the part most explanations stop at. This guide goes one step further, because a stage name is really a message to your users about how much they can rely on what you just shipped. Below: what each stage means, how release candidates are numbered so tools sort them correctly, how real projects run their RC phase, and what to tell users at each step.

Jump to: The stages at a glance · RC vs beta · RC vs final release · Version numbers · How real projects do it · What to tell users · Do you need one?

The release life cycle at a glance

Software that ships as discrete versions usually moves through four stages. Each one is a different promise.

Stage What it means Who it’s for Still changing? Example version
Alpha Early and incomplete. Features are missing and things break. The team, and a few people who asked for it Everything 2.0.0-alpha.3
Beta Feature-complete or close to it. Works, with known rough edges. Outside testers and early adopters Details, based on feedback 2.0.0-beta.2
Release candidate Believed ready. No known blocking bugs. Anyone willing to verify it before launch Only fixes for serious bugs 2.0.0-rc.1
General availability (GA) The supported, stable release. Everyone No — changes go in the next version 2.0.0

A few terms you’ll meet around the edges:

  • Pre-alpha covers everything that happens before formal testing starts — prototypes and nightly builds, for example.
  • Closed beta and open beta differ only in who can get in: an invited group or anyone who wants it.
  • Stable release is the usual name for the build that passed every candidate stage. RTM (release to manufacturing, or “going gold”) is the moment that build is signed off, and it dates from when the next step was pressing discs. GA is the later point when the product is actually available — for boxed software the gap could be days or months, and for software delivered online the two have collapsed into one.
  • Preview and early access are marketing names that can mean alpha or beta depending on the company. If a vendor doesn’t say which, assume the less stable one.

Release candidate vs beta

The difference is whether the build is frozen.

A beta is still a conversation. The team is asking whether the feature works the way people need it to, and the answers change the product: a setting gets renamed, a flow gets reworked, an API response gains a field. Known bugs ship in a beta on purpose and are listed in its notes.

A release candidate has stopped listening for opinions. Nothing new goes in. The only question is whether a problem exists that’s bad enough to stop the launch — a crash, data loss, a broken upgrade path, a security hole. A typo in a tooltip doesn’t produce a second candidate. A migration that corrupts a table does.

That gives you a simple test for which label fits what you’re about to publish:

  • If feedback could still change what the release does, it’s a beta.
  • If feedback could only change whether the release ships, it’s a release candidate.

Teams get this wrong in one direction far more than the other: they call something an RC and then keep merging features into it. Every merge resets the confidence the label was supposed to signal, and the testers who verified rc.1 have verified nothing about rc.2.

Release candidate vs the final release

If everything goes well, the difference is the version number and nothing else. The build that survived the RC window is promoted to the final release under the stable version number.

What changes is the promise attached to it:

  • Support. A release candidate comes with no guarantee. The final release is the one the vendor supports, patches, and documents.
  • Default installation. Package managers skip pre-release versions unless you ask for them, so nobody receives a release candidate by accident. The final release is what install and update deliver.
  • Upgrade path. Vendors commit to upgrades from one stable version to the next. Moving from an RC to the final release usually works, but it’s rarely a tested path.

When a candidate does fail, the fix is published as a new candidate — rc.2, rc.3 — and the clock restarts.

How release candidates are numbered

In semantic versioning, a pre-release is the target version followed by a hyphen and an identifier:

2.0.0-alpha.1 < 2.0.0-beta.1 < 2.0.0-rc.1 < 2.0.0-rc.2 < 2.0.0

A pre-release always sorts below the version it’s leading up to, which is why 2.0.0-rc.1 isn’t “newer than” 2.0.0. The alpha, beta, rc order above works because identifiers made of letters are compared alphabetically, and those three happen to sort the way the stages run.

One detail causes real bugs: keep the dot before the number. SemVer compares dot-separated identifiers one at a time, and purely numeric ones are compared as numbers. Glue the number to the letters and the whole identifier is compared as text:

Written as Sorts as
rc.2, rc.10 rc.2 < rc.10 — correct
rc2, rc10 rc10 < rc2 — the tenth candidate looks older than the second

Ecosystems add their own rules on top:

  • npm excludes pre-releases from range matching by default: a version with a pre-release tag only satisfies a range when the range itself names a pre-release of that same major.minor.patch, so ^2.0.0 won’t pick up 2.1.0-rc.1. When you publish, pass a dist-tag — npm publish --tag next — so a candidate doesn’t end up as latest. Current npm releases require it: publishing a pre-release version without an explicit tag is an error.
  • Python uses the PEP 440 scheme, which drops the hyphen and the dot: 2.0.0a1, 2.0.0b2, 2.0.0rc1. By default pip only installs stable versions. It considers a pre-release when you pass --pre, when your requirement names one explicitly, or when a pre-release is the only version that satisfies the requirement.
  • GitHub Releases has a “This is a pre-release” checkbox that tells users the release isn’t ready for production, and a pre-release can’t be marked as the latest release. You can set it from a workflow based on the tag — the pattern is in the action-gh-release guide.

If your releases are automated, the tooling already has a mode for this. semantic-release publishes pre-releases from dedicated branches, Changesets has a pre-release mode you enter and exit, and Release Please has a prerelease versioning strategy for the same job.

How real projects run a release candidate

The definition is shared. The practice varies more than you’d expect.

The Linux kernel treats the RC phase as most of the release cycle. After a merge window of about two weeks, -rc1 is tagged, and from then on only patches that fix problems are supposed to go in. A new candidate follows about once a week, and according to the kernel’s own process documentation a normal series reaches somewhere between -rc6 and -rc9 before the final version is released. Here the candidates aren’t a last-minute check; they’re the stabilization process itself.

Apple ships a Release Candidate of each iOS and macOS version to developers and public beta testers shortly before launch. Until late 2020 the same build was called the GM seed, for golden master. When Apple switched names, its release notes said the term Release Candidate “replaces GM seed and indicates this version is near final”.

WordPress runs several betas and then a series of release candidates before each major version. Its release handbook puts a hard string freeze at the Release Candidate stage: text strings in the application can no longer be changed, which gives translators a target that won’t move.

Python stops accepting new features at the first beta, and tightens again at RC. Its developer guide says a branch preparing for a release candidate can only take bug fixes that other core team members have reviewed, generally for issues severe enough to deserve fixing before the final release, such as crashes. The stated goal is no code changes at all between an RC and the final release.

Kubernetes applies the same vocabulary to individual features rather than whole versions. Per its feature-stage definitions, an alpha feature is disabled by default and support for it may be dropped at any time, a beta feature is usually enabled by default but its details may still change, and a GA feature is always enabled — you can’t turn it off. Each feature moves through those stages on its own schedule.

The pattern across all of them: the label is only worth something because a rule stands behind it. “Fixes only.” “Strings frozen.” “Disabled by default.” Without the rule, alpha, beta, and RC are just adjectives.

What to tell users at each stage

Here’s the part the definitions leave out. Each stage needs a different kind of release note, because the reader is deciding something different each time.

Stage The reader’s question What the notes should contain
Alpha “Is this worth my time yet?” What works, what’s missing, and a clear warning that data and APIs may not survive
Beta “What should I try, and where do I report problems?” What’s new, the known issues, what feedback you want, and how to send it
Release candidate “Will this break my setup when it ships?” Breaking changes, upgrade steps, the planned GA date, and what counts as a blocker
GA “What do I get, and what do I have to do?” The full story since the last stable version, written for people who skipped every pre-release

Three habits make this work in practice.

Say what’s frozen. A release candidate announcement should state plainly that nothing new will be added and that only serious bugs will change the build. That sentence is what tells integrators it’s safe to start testing against it. If you publish an API, pair it with the dates — the same discipline covered in how to write API release notes.

Tell people what a blocker is. “Please report any problems” gets you a hundred tooltip typos. “We’ll delay the release for crashes, data loss, failed upgrades, and security issues” gets you the reports you need.

Write the GA notes from scratch. The most common mistake at launch is publishing the diff between the last candidate and the final build — which, if things went well, is empty. Most of your users never installed a pre-release. The GA notes have to cover everything since the previous stable version, and in a changelog that means folding the alpha, beta, and RC entries into a single entry for the final release.

A release candidate announcement can be this short:

## 2.0.0-rc.1 — release candidate

This is the build we intend to ship as 2.0.0 on December 2.
No new features will be added. From here we'll only fix
crashes, data loss, upgrade failures, and security issues.

**Please test:** upgrading from 1.9.x, the new import API,
and SSO login.

**Breaking changes since 1.9:** see the upgrade guide.
**Found a blocker?** Open an issue with the "2.0-blocker" label.

For where each of these should be published — in the product, by email, on the public page — see how to communicate product changes to your users. Mobile apps have their own channel for the pre-release stages in TestFlight and Play testing tracks, covered in mobile app release notes.

Does your product need release candidates?

It depends on who installs your software.

You need them if other people’s systems depend on a specific version of yours. Libraries, SDKs, self-hosted software, desktop and mobile apps, operating systems, and public APIs with versioned contracts all fit. Your users can’t be moved to the fix in an hour, so a bad release costs them real work, and a candidate lets the most motivated of them find the problem first.

You probably don’t if you run a continuously deployed web app. There’s one production version, you control it, and a rollback takes minutes. The stages still exist, but they’ve changed shape: a feature flag that’s on for staff is your alpha, a percentage rollout or an opt-in toggle is your beta, and flipping the flag to everyone is GA. There’s no release candidate because there’s no frozen build to be a candidate.

Even then, the vocabulary earns its keep. Labelling a feature “beta” in the interface is a promise about stability, and removing the label is an announcement worth making. If you treat that moment as a release — with a date and a note — users learn that your labels mean something. That’s the communicate step of release management, and it applies whether you ship twice a year or twenty times a day.

The short version

  • A release candidate is a frozen, feature-complete build that becomes the final release unless a serious bug is found.
  • It differs from a beta in that feedback can no longer change what the release does, only whether it ships.
  • It differs from the final release in the support promise, not in the code.
  • Number it X.Y.Z-rc.N, with the dot, so tools sort it correctly and package managers keep it away from people who didn’t ask for it.
  • Tell users what’s frozen, what counts as a blocker, and when GA is planned — then write the GA notes for the people who skipped every pre-release.

ReleasePad drafts your release notes from the work your team already did, so the GA announcement isn’t an afterthought. Publish to a public changelog page and an in-app widget, with the GitHub integration drafting entries from your commits and pull requests. Try it free →


Further Reading

Frequently Asked Questions

What is a release candidate?

A release candidate, or RC, is a build that the team believes is ready to ship as the final version. It's feature-complete, it has passed the team's own testing, and no known blocking bugs remain. It's published so a wider group can confirm that under real conditions. If nothing serious turns up, the same code is released as the stable version; if something does, the team fixes it and publishes another candidate.

What is the difference between a release candidate and a beta release?

A beta is still being changed: features may be adjusted, known bugs are listed, and feedback shapes the product. A release candidate is frozen. Nothing new goes in, and the only changes accepted are fixes for serious problems found in the candidate itself. A beta asks what should change; a release candidate asks whether there's any reason not to ship this exact build.

What is the difference between a release candidate and the final release?

Ideally, only the version number. If a release candidate survives its testing window with no blocking bugs, that same build is promoted to the stable release, often called general availability or GA. The practical difference is the support promise: a release candidate carries no guarantee and isn't installed by default by package managers, while the final release is the version the vendor supports and recommends for production.

What does general availability (GA) mean?

General availability is the point where a version is officially released to everyone and supported for production use. It follows the pre-release stages of alpha, beta, and release candidate. GA is when the full documentation, the support commitment, and the public announcement apply. It isn't the same as release to manufacturing (RTM, or going gold), which is the earlier moment the final build is signed off; for boxed software, GA could follow RTM by days or months.

How do you number a release candidate version?

In semantic versioning, add a hyphen and a pre-release identifier to the version it's a candidate for: 2.0.0-rc.1, then 2.0.0-rc.2, and finally 2.0.0. Keep the dot before the number so candidates sort numerically, otherwise rc10 sorts before rc2. Python packages follow the PEP 440 version scheme and write the same thing as 2.0.0rc1. A release candidate always sorts lower than the final version it precedes.

What is a release candidate in iOS?

It's the last pre-release build of an iOS version that Apple gives to developers and public beta testers before the public launch. Apple has used the name Release Candidate since late 2020, when its release notes stated that the term replaces GM seed (GM stood for golden master) and indicates the version is near final.

release-candidate release-management versioning beta semantic-versioning release-notes

Ready to put this into practice?

Your changelog shouldn't be an afterthought.

ReleasePad makes it easy to publish great release notes — from a public changelog page to an in-app widget, GitHub integration, and analytics. Free to get started.

Get started — it's free
Try me now!