Keeping Read the Docs Versions Under Control with Automation Rules
Read the Docs turns every tag into a potential published version. Use automation rules, active/hidden flags, and redirects to keep the version picker clean and builds under control.
30 Jan 2026, 19:45 UTC

The problem: every tag becomes a published version
Connect a repository to Read the Docs and it will happily treat every branch and tag as a documentation version. On a long-lived project, that means the version picker fills with old releases, pre-release tags, and stray branches, and each push to an active version can trigger a build. Readers get a cluttered selector, and maintainers get a build queue full of work nobody asked for. The useful takeaway: Read the Docs gives you dashboard-level automation rules and per-version active/hidden flags to control this — but notably, there is no regex for version matching in .readthedocs.yaml, and the YAML file does not control which versions exist.
How Read the Docs actually decides what to build
Read the Docs creates a version for each branch and tag it sees in your repository. Whether a version is built and published depends on its state, managed from the project's Versions page in the dashboard:
- Active: the version is built and publicly served at a URL like
/en/<version>/. - Inactive: the version still exists but is not built or served.
- Hidden: an active version that is built but omitted from the version picker and search indexing — useful for pull-request previews or work-in-progress branches.
Two important consequences follow. First, version control is a dashboard/API concern, not a YAML concern — .readthedocs.yaml controls how a build runs (OS, tool versions, Sphinx/MkDocs commands), not which versions exist. Second, new tags do not automatically become active builds; by default they start inactive unless an automation rule activates them.
Worked example: automation rules for release tags only
Say your repository has a main branch, stable tags like v1.2.0, and pre-release tags like v2.0.0-rc1. You want stable tags published automatically and pre-releases ignored. In the Read the Docs dashboard, go to Admin → Automation Rules and create rules like:
- Rule 1 — Match:
v*on tags; Action: Activate version. This publishes new stable tags as they appear. - Rule 2 — Match:
*-rc*(or your pre-release suffix) on tags; Action: Hide version or simply leave them inactive, so they never appear in the picker.
Automation rules support simple wildcard matching on version names (check the current dashboard UI for the exact match types offered, such as "matches pattern" or semver-style comparisons). Because rule syntax and available actions have evolved over time, verify the options in your project's dashboard rather than assuming a specific regex dialect.
Your .readthedocs.yaml stays focused on the build itself, for example:
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
sphinx:
configuration: docs/conf.py
python:
install:
- requirements: docs/requirements.txt
This file lives at the repository root and applies to every version's build. Run a commit to main and confirm in the dashboard's Builds tab that the default version builds successfully.
Verifying the setup
- Push a new tag matching your activation rule (e.g.,
git tag v1.3.0 && git push origin v1.3.0, run locally with push permissions on the repo). - In the dashboard's Versions page, confirm the tag appears as active and a build is queued or completed.
- Open the built docs and use the version picker (the flyout menu, usually bottom-left) to confirm
v1.3.0is listed and loads at/en/v1.3.0/. - Push a pre-release tag like
v2.0.0-rc1and confirm it does not appear in the picker.
Pruning old versions
There is no built-in "keep last N releases" cleanup setting. Pruning is manual or scripted: deactivate or delete stale versions from the Versions page, or use the Read the Docs REST API v3 to list versions and update their active state. If you script this, consult the current API documentation for the exact endpoints and required permissions — endpoint shapes have changed between API versions, so don't hardcode paths from older blog posts. A conservative approach is to deactivate rather than delete: deactivated versions stop being built but can be reactivated if someone needs the old docs again.
Trade-offs and limitations
- Deactivating a version removes its URL. Existing external links to
/en/v1.0.0/will break unless you add redirects (Admin → Redirects) pointing old paths to a supported version. - Rules act on new versions. Tags that already exist when you create a rule may need to be activated or hidden by hand.
- Hidden is not private. A hidden version is still reachable by direct URL; don't use it for embargoed content.
Actionable closing
- Audit your Versions page and deactivate versions nobody links to anymore.
- Add automation rules so only stable release tags activate automatically.
- Add redirects from retired version URLs to the current stable docs.
- Re-check the version picker after your next release to confirm it shows only what readers need.
The result is a picker that answers "which release am I looking at?" instead of a museum of every tag you ever pushed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.