Versioning, stability, deprecation, and support policy
At a glance
Section titled “At a glance”Every NextPDF documentation page carries lifecycle fields in its front matter:
stability, since, deprecated_since, replaced_by, version_lifecycle,
and eol_date. Those fields already encode a support contract. This page states
that contract in one place so a production team can read any page’s metadata and
risk-assess pinning a version.
NextPDF follows Semantic Versioning 2.0.0 for its release numbers and
Conventional Commits 1.0.0 for changelog generation. The service provider
interface (the public contracts in NextPDF\Contracts and NextPDF\Event) is
governed by the same rules; see
SPI stability rules for the
per-contract @stability tag mechanics. This page is the broader policy that
the SPI rules specialize.
Semantic versioning for NextPDF
Section titled “Semantic versioning for NextPDF”A release version is MAJOR.MINOR.PATCH. The position that changes tells you
what can change in your code:
| Increment | What it means | What may break |
|---|---|---|
Major (3.x → 4.0.0) | Breaking changes are permitted. | A stable contract may change signature or be removed; a deprecated symbol marked in the previous major may be deleted; default behavior may change. |
Minor (6.0 → 6.1.0) | Backward-compatible additions. | Nothing for a stable contract. A published stable interface gains no new required methods; growth comes from new contracts/interfaces, optional methods on concrete classes, and new constructor/config options with defaults. An experimental contract may change here, with a deprecation notice first. |
Patch (3.2.0 → 3.2.1) | Backward-compatible bug fixes. | Nothing intentional. Behavior converges toward the documented contract. |
The practical rule for a stable surface: a Composer constraint such as
^3.2 receives every minor and patch release of its major line without a
breaking change. Breaking
changes land only on a major boundary.
{ "require": { "nextpdf/core": "^3.2" }}Pin more tightly (for example ~3.2.0) when you depend on an experimental
contract, because an experimental contract may change in a minor release.
Stability labels
Section titled “Stability labels”A page’s stability field, and a contract’s source @stability tag, draw from
the same vocabulary. The label states the strength of the compatibility promise.
| Label | What it guarantees | Where it changes |
|---|---|---|
stable | Production-ready. Safe to depend on. No breaking change in a minor or patch release. A stable interface (such as the NextPDF\Contracts SPI) gains no new required methods in a minor or patch — backward-compatible growth arrives on a new contract, as an optional method on a concrete class, or via constructor/config options with defaults. | Major release only. |
beta | Feature-complete and usable, but the surface is not yet frozen. Treat it like experimental for pinning: wrap or pin tightly. | May change in a minor release, with a deprecation notice first. |
experimental | Usable, but explicitly not frozen. NextPDF may ship a tested engine implementation while the public contract still moves. | May change in a minor release, with a deprecation notice first. |
deprecated | Scheduled for removal. The page or contract states its replacement and the major in which it is removed. | Removed in the next major; never in a minor or patch. |
The streaming contracts NextPDF\Contracts\CursorInterface and
NextPDF\Contracts\StreamingWriterInterface are real examples of
experimental surfaces: NextPDF ships final, tested implementations, but the
public contract may still change in a minor release. Pin tightly or wrap such a
contract behind your own adapter before you depend on it in production.
Deprecation lifecycle
Section titled “Deprecation lifecycle”Deprecation is a defined, four-step path. It always names the replacement, and removal is always deferred to a major boundary:
- Mark. The owner sets
@stability deprecatedon a contract (ordeprecated_sinceon a page) and records the replacement and the removal major. On a page,deprecated_sinceis the version that introduced the deprecation andreplaced_byis the canonical successor path. - Notice. The deprecation is announced in the changelog for the release that marks it.
- Overlap. The deprecated surface and its replacement coexist for at least one minor release, so you can migrate without a flag day.
- Remove. The surface is removed in the stated major release. Removal never happens in a minor or patch release.
A page-level example that has completed the whole arc: the legacy
/docs/cookbook/php/sign-pades/ recipe was marked deprecated_since: "3.0.0"
with replaced_by: /docs/cookbook/php/sign-pades-b-b/, coexisted with its
successor through the overlap window, and has since been retired — the old URL
now answers with a permanent redirect to the successor recipe, so links written
against the deprecated page keep working after removal.
Plan a migration as soon as a surface is marked deprecated. Because the
replacement is always stated and the two overlap for at least one minor, you can
move before the removing major arrives.
Version lifecycle and security support
Section titled “Version lifecycle and security support”The version_lifecycle field classifies how a documented version line is
maintained. The values are:
version_lifecycle | Meaning | Receives |
|---|---|---|
active | The current line under active development. | Features, fixes, and security fixes. |
lts | A long-term-support line. | Fixes and security fixes for its support window. |
maintenance | Past active development, still maintained. | Security fixes and serious-bug fixes. |
frozen | No further functional change planned. | Security fixes only, where applicable. |
eol | End of life. | Nothing. Upgrade is required. |
When a line reaches end of life, its eol_date records the date (ISO 8601,
YYYY-MM-DD). A page with version_lifecycle: eol and a past eol_date is a
signal to migrate off that line: it no longer receives fixes, including security
fixes.
This is a policy statement, not a calendar promise. The fields tell you the
class of support a line is in; consult the changelog and release notes for the
concrete version that carries a given fix. Security fixes are backported to the
lines whose lifecycle still includes them (active, lts, and maintenance),
not to lines marked frozen-without-applicability or eol.
PHP version support window
Section titled “PHP version support window”NextPDF Core requires PHP >=8.4 <9.0. That window is declared in the engine’s
composer.json and is the single source of truth; the premium packages
(nextpdf/pro, nextpdf/enterprise) require the same range.
- The lower bound (
>=8.4) is the minimum runtime. Raising it is a breaking change and lands only on a major boundary. - The upper bound (
<9.0) excludes the next PHP major until it has been validated. Support for a new PHP major is added in a NextPDF release, not assumed.
Documentation pages also carry a compatibility list of the PHP minor versions
a recipe is verified against. A page may list older minors (for example
["8.1", "8.2", "8.3", "8.4"]) where the recipe is portable, while the engine’s
hard install floor remains >=8.4. When in doubt, the composer.json constraint
wins over a page’s compatibility hint.
How to read a page’s lifecycle front matter
Section titled “How to read a page’s lifecycle front matter”Use these six fields to assess any page before you build on it:
| Field | Type | How to read it |
|---|---|---|
stability | stable | beta | experimental | deprecated | The compatibility promise for the surface the page documents. |
since | SemVer (e.g. "3.1.0") | The version that introduced the documented surface. Your install must be at least this version. |
deprecated_since | SemVer or empty | If set, the surface is deprecated; the value is the version that deprecated it. Empty means not deprecated. |
replaced_by | Site path or empty | When deprecated, the canonical successor page to migrate to. |
version_lifecycle | active | lts | maintenance | frozen | eol | The maintenance class of the documented line. |
eol_date | ISO date or empty | When version_lifecycle is eol, the end-of-life date. Empty otherwise. |
A worked read: a page with stability: stable, since: "3.0.0",
deprecated_since: "", and version_lifecycle: active documents a
production-ready surface that has existed since 3.0.0, is not deprecated, and
sits on the actively maintained line. You can depend on it under a ^ major
constraint. A page with stability: deprecated and a non-empty replaced_by
is a migration signal: read the successor page and plan the move before the next
major.
Conformance
Section titled “Conformance”This policy conforms to Semantic Versioning 2.0.0 for version numbering and to
Conventional Commits 1.0.0 for changelog generation. The PHP support window is
the >=8.4 <9.0 constraint declared in the engine composer.json. This page
makes no normative standards claim of its own; it documents the support contract
the lifecycle front-matter fields already encode.
See also
Section titled “See also”- SPI stability rules — the
per-contract
@stabilitytag and the four backward-compatibility promise classes (interface, enum, frozen value-object, experimental). - CSS support matrix — the truth-audited per-module support state for the HTML and CSS rendering pipeline.
- Reference index — the entry point for API, configuration, and compatibility reference material.