Versioning
August 6, 2026 · View on GitHub
This page covers the version contract Prisma Next offers to its users and ecosystem, and the mechanism that delivers it. The first half is the policy you can rely on; the second half is the procedure maintainers follow to honour it.
Pre-1.0: deliberately unstable
Note: releases now ship on the v8 RC line (
8.0.0-rc.N) rather than as0.xminors — see The v8 RC line below. The latitude described here carries over: RC respins may include breaking changes until8.0.0final ships.
Prisma Next is in early access and is deliberately pre-1.0. Per SemVer §4, the 0.x range carries no backwards-compatibility promise, and we use that latitude. Concretely:
- Breaking changes ship in regular minor bumps. A
0.7.0to0.8.0upgrade may include API removals, semantic changes to existing APIs, or contract-format changes. - Releases are frequent. The cadence is "ship a minor whenever the next batch of work is cohesive enough to warrant one", not a fixed weekly/monthly schedule. Expect minors more often than you would expect them from a 1.x project.
- There are no patch releases of older minors. Once
0.8.0ships,0.7.xreceives no further updates — no security patches, no regression fixes, no cherry-picks. If you hit a regression in the latestlatestwe may cut a0.8.1, but you are expected to keep up rather than pin and wait. - The agent-driven upgrade skill is the long-run answer to keeping consumers current with minimal churn. Each minor will ship with a machine-readable upgrade recipe that the skill applies; the upgrade contract — what the recipes are allowed to assume, what they're allowed to change — will be documented separately in
docs/oss/upgrade-policy.mdonce that work lands. Until then, breaking changes are surfaced through release notes only.
If your project cannot tolerate this cadence today, Prisma Next is not the right choice yet. The promise we make instead is that you can always read a single number — the root package.json version of any commit — and know exactly what you have.
Lockstep across the workspace
Every workspace package — publishable, private, the workspace root, and example apps — carries the same version. One read of root package.json answers "what version is this code?" for the entire repository.
This invariant has consequences that ecosystem participants need to plan for:
- Agent skills, the upgrade skill, and any other tooling we ship alongside the framework version in lockstep with it. A skill installed at the same time as
@internal/postgres@0.8.0is a0.8.0skill and reasons about a0.8.0contract. There is no separate skill-version axis to track. - Extension authors that depend on internal framework packages must pin those dependencies to the framework version their consumers will use. If your extension depends on
@internal/sql-core(an internal framework package), publish each version of your extension targeting one specific Prisma Next minor and pin to it exactly ("@internal/sql-core": "0.8.0", not"^0.8.0"). Internal packages do not promise inter-minor compatibility —0.8.xand0.9.xmay have incompatible internals even when the user-visible surface looks similar. The extension's published version range communicates which framework minor it targets. - Internal packages are never published, but they still version in lockstep so a contributor cloning the repo at any commit sees one consistent answer to "what version is this code?" The
private: trueflag meanspnpm publishskips them.
If lockstep ever broke — if a private package or example carried a different version — the "one read of root tells you everything" invariant would be silently violated. Every CI gate that checks the root version on publish (today: pre-publish dependency-specifier validation; tomorrow: the upgrade-skill recipe-presence check that fires on root version changes) is built on this assumption.
The v8 RC line
Prisma 8 ships as a release-candidate line ahead of 8.0.0 final: releases are versioned 8.0.0-rc.1, 8.0.0-rc.2, … with the counter advancing on every release publish. "The v8 RC" is the product name; the version number underneath iterates freely, and there is no promise that the final RC is literally numbered rc.1. Versions are immutable on npm — a botched publish burns a counter value, which is fine; skip it and never reuse a number.
For every package this repository publishes, latest tracks the newest release — RC or stable. These package names have no pre-v8 stable audience to protect: a bare npm install of any of them is an early-access install, and early-access users are expected to keep up (see the pre-1.0 policy above). Existing installs are unaffected — lockfiles pin resolved versions, and ^0.x ranges can never resolve to an RC (pre-releases don't match stable ranges), so nobody is moved onto the RC line by npm update; new installs simply get the newest RC.
The frozen-latest concern — never surprising an existing stable audience — applies to the bare prisma package, which this repository does not publish. Its v8 bin shim lives in prisma/prisma-cli; that repository publishes v8 builds under next while latest stays on Prisma 7 (published from the v7 branch's pipeline) until 8.0.0 final.
The transition onto the RC line is a one-time bump from the last 0.x stable to 8.0.0-rc.1; pnpm bump-version encodes it (a pre-8 stable base advances to 8.0.0-rc.1, an RC base advances its counter). There are no further 0.x minors.
Dist-tag convention
The npm registry exposes Prisma Next under these dist-tags:
latest— the most recent release, RC or stable (8.0.0-rc.Non the RC line). Default for any barenpm install. Newlatestreleases happen automatically when a release PR merges (see procedure below).dev— every push tomainthat doesn't change the rootversionproduces a<base>-dev.Ntarball under this tag (on the RC line:8.0.0-rc.X-dev.N). Use these to pin reproductions, install internal CI runs, or hand someone a "try@devto get the bleeding edge" link. No stability promise — they may be yanked freely.beta— reserved for hand-cut previews ahead of significant changes. Routine releases do not use this tag.
The pr dist-tag was used historically to publish per-PR previews; PR previews now go through pkg.pr.new (.github/workflows/preview-publish.yml) instead. The legacy pr tag is left as-is on the registry.
Who can publish
Publishing requires:
- Membership in the maintainer team (see Governance) — pushing to
mainor merging a release PR is restricted to maintainers. - A green run of the
Publish to npmworkflow. The workflow uses npm OIDC trusted publishing — no long-livedNPM_TOKENexists in repository secrets, so a leaked secret cannot be used to publish out-of-band. Each published tarball carries an npm provenance attestation tying it to this repository and the workflow run that produced it. - The workflow only publishes from
main. Dry-runs are permitted from any branch (see "validating publish changes" below); every step that would mutate external state is independently guarded.
Mechanism: how we deliver the contract
The version Prisma Next ships is the version field of the root package.json. The publish workflow (.github/workflows/publish.yml) reads this value at the workflow's git ref and refuses to publish anything else. There is no workflow_dispatch input to override the version, no per-package version drift, and no separate "release manifest" file. Anyone — human or agent — can answer "what version are we on?" by reading a single file under git.
This is by design. Two of the three other places a version could live cause silent problems:
- Querying the npm registry for the latest tag (the previous behaviour) makes the next minor implicit. A yanked release, a manually-rewritten dist-tag, or registry latency all silently shift what the next CI build calls itself.
- A separate
versions.jsonorrelease.tomlwould diverge from the per-packageversionin tooling that only inspectspackage.json(npm, dependency analyzers, supply-chain scanners, downstream consumers). Keeping the source inpackage.jsonmeans there is nothing to keep in sync.
scripts/set-version.ts is what enforces lockstep: a single invocation walks every workspace package.json and writes the requested version. The publish workflow uses the same script, so per-package and root values cannot diverge through the publish path.
The publish workflow is triggered by a change to the root version: a push to main whose root package.json carries a different version than the previous tip is recognised as a release bump and ships the new version under dist-tag latest — on the RC line that means latest moves to the new 8.0.0-rc.N, and the accompanying GitHub Release is marked pre-release. Pushes that don't change the root version produce <base>-dev.N tarballs under dist-tag dev instead. This is what makes "merge the release PR" the publish trigger — there is no separate dispatch step.
A growing set of pre-publish gates run as part of the workflow:
- Dependency-specifier check (
pnpm check:publish-deps) — fails the publish if any resolvedpackage.jsonwould carry an unrewrittenworkspace:*orcatalog:specifier into the registry. - Release-notes presence check (
pnpm check:release-notes) — fires forlatestpublishes only. The Release body is the committeddocs/releases/v<version>.md, published viagh release create --notes-file; this check fails the publish when that file is missing. There is no--generate-notesfallback. A PR-mode variant runs in CI (.github/workflows/ci.yml) and fails a release PR that bumps the rootversionwithout committing the matching notes file, so the omission is caught in review rather than at publish. - More gates will accumulate here as the upgrade-skill machinery lands (recipe-presence check fired on root version changes, etc.). The root-version-as-trigger model is the hook these checks plug into.
Procedure: cut the next release
The release cadence is one PR per release (on the RC line: one PR per rc.N). A maintainer:
- Runs the
publish-npm-versionskill (seepublish-npm-version). The skill creates a fresh worktree offorigin/main, drivespnpm bump-version, and opens a PR in the maintainer's name. Using a skill rather than a GitHub workflow ensures the PR carries real maintainer credentials so CI runs on it normally. - Authors the release notes. The release PR must include a committed
docs/releases/v<version>.md; its contents become the GitHub Release body verbatim (gh release create --notes-file), so there is no auto-generated PR-title summary to fall back on. The PR-mode release-notes gate fails the PR if the file is missing, making notes authoring part of preparing the release. Thepublish-npm-versionskill drafts this file automatically before opening the PR by running thedraft-release-notesskill, which enumerates the release's merged PRs, triages them, and writes the categorized notes (breaking changes first) plus a matchingCHANGELOG.mdentry — the maintainer reviews the result in the PR rather than authoring from scratch. - Reviews and merges the PR. This is the point where humans verify there are no in-flight breaking changes that need release-notes attention. The merge itself is the publish trigger: the resulting push to
maincarries the bumped rootversion, the publish workflow detects the change, and publishes<version>under dist-taglatestplus a matching GitHub Release (marked pre-release on the RC line) whose body is the committed notes file. No separate dispatch step is required.
If the publish needs to be re-run (transient registry failure, etc.), a maintainer can dispatch the Publish to npm workflow from main with dist-tag=latest and dry-run=false; the workflow re-publishes the version currently committed at HEAD. This is the same path used to cut a hand-rolled beta (dist-tag=beta).
Procedure: patch the current minor
On the RC line there are no patch releases — a fix ships as the next rc.N via the routine procedure above. This section applies only while releases are stable versions (before the RC transition, or after 8.0.0 final). Patches are not part of the routine cadence and only apply to the current minor (per the pre-1.0 policy above — older minors are not maintained). If a freshly-published latest ships a regression that must be addressed before the next minor:
- Land the fix as a small PR.
- On a follow-up PR, run
node scripts/set-version.ts <major>.<minor>.<patch+1>to advance every workspace package to the patch version. - On that same PR, author
docs/releases/v<major>.<minor>.<patch+1>.md. The release-notes gate enforces a committed notes file for everylatestrelease, patches included — a patch with no notes file fails the publish. A patch entry is usually short (a single Fixes item), but it is still the Release body. - Merge to
main. The merge changes the rootversionand auto-publisheslatestvia the same path as a minor bump.
The skill is not used for patches because the bump shape is different (patch+1, not minor+1); the explicit set-version.ts invocation is the procedure.
Procedure: validate publish changes
The publish workflow's dry-run mode (the input default) can be invoked from any branch to validate that the publish pipeline still works after touching publish.yml, set-version.ts, determine-version.ts, the publish script, or any of the build scripts. A dry-run exercises pnpm publish --dry-run against every publishable workspace package, runs the pre-publish gates, and skips the registry publish + GitHub Release.
Non-goals
- Maintenance of older minors. Stated above as policy: in the
0.xrange, you upgrade. There is no tooling for cutting a0.7.xpatch after0.8.0ships, and that is intentional. - A scripted
betacadence. Thebetadist-tag exists but cutting beta builds is a manualworkflow_dispatch. (The RC cadence, by contrast, is the routine scripted path — see the RC-line section above.) - Independent per-package versioning. Lockstep is the invariant the rest of the contract is built on; per-package versions would require redesigning
set-version.ts, the publish flow, and the upgrade-skill recipe model.