API stability¶
TL;DR. Public
pulse.*properties, the/actuator/pulse*endpoint shape, metric names, and types in non-internalpackages are stable across 2.x minor versions. Everything under an.internalpackage, the auto-configuration class names, and the bean names listed in the SPI catalog are deliberately unstable.
Pulse 2.0 introduced a hard line between the API you're meant to depend on and the wiring that makes it work. This page is the explicit contract.
What's stable in 2.x¶
Changes to these break a 2.0 → 2.x upgrade and will only land on a major
version bump:
- Configuration keys under
pulse.*. Renames go through a deprecation cycle: the old key still binds, a startup warning fires, and theadditional-spring-configuration-metadata.jsonentry carrieslevel: errorplus a replacement pointer. - Public types in non-
internalpackages:io.github.arun0009.pulse.<feature>(e.g.SpanEvents,PulseEventContext,DependencyClassifier,ErrorFingerprintStrategy,TenantExtractor,ContextContributor,PulseRequestMatcher,HostNameProvider,ResourceAttributeResolver,PulseEnforcementMode). - Metric names and their tag keys:
pulse.*meters and their low-cardinality tags are pinned. Tag values may expand (e.g. a newreasonbucket) within a minor release. - Actuator endpoint shapes:
/actuator/pulse,/actuator/pulse/{slo,effective-config,runtime,config-hash,enforcement}. Existing JSON keys keep their meaning; new keys may be added. - Auto-configuration activation contract: each feature's top-level
enable toggle (
pulse.<feature>.enabled) and, where declared, itsenabled-whenblock. - SPI contracts listed in Extending Pulse (SPIs).
- MDC keys Pulse writes:
traceId,requestId,userId,tenantId,priority,retry.depth,service.name,deployment.environment. - HTTP headers Pulse reads / stamps:
traceparent,tracestate,baggage,Pulse-Request-Id,Pulse-Timeout-Ms,Pulse-Tenant-Id,Pulse-Priority,Pulse-Retry-Depth.
What's explicitly unstable¶
These may be renamed, moved, or removed in any minor release without a deprecation cycle. Do not import or depend on them:
*.internal.*packages. Everything underio.github.arun0009.pulse.<feature>.internalis wiring — concrete@Configurationclasses,BeanPostProcessorfactories, instrumented@Beannames that aren't on the override-worthy list, private helper classes. Spring Boot's auto-configuration contract is "wire by activation property, not by class name" and Pulse follows that strictly.- Auto-configuration class names. Reference features by their
activation property or
@ConditionalOnMissingBeanoverride, never by the FQCN of the@AutoConfigurationthat wires them. - Built-in
ObservationHandler<PulseEventContext>implementations. Replace behavior by registering your own handler bean; do not extend or referencePulseEventCounterObservationHandler,PulseEventSpanObservationHandler,PulseEventLoggingObservationHandlerdirectly. - Internal log messages. The names of Pulse's log events
(
Pulse retry-amplification detected, etc.) are not an API. If you parse them, treat each string as best-effort. - Bean names not in the override table. The SPI catalog
lists the bean names gated on
@ConditionalOnMissingBean. Anything outside that table — in particular additiveBeanPostProcessors and chain terminals — may be renamed.
Deprecation policy¶
When a stable surface must change:
- The new surface lands in a minor release, alongside the existing one. Both work simultaneously.
- The old surface is marked
@Deprecated(forRemoval = true)(for code) or gets a"deprecation"entry with"level": "error"and a"replacement"pointer (for configuration keys). - A startup log line fires whenever the old surface is actually used, so
grep WARNon boot logs is enough to spot every deprecated call site. - The old surface is removed in the next major release (2.x deprecation → removed in 3.0).
Example: pulse.sampling.probability was deprecated in 2.0 in favour of
Spring Boot's management.tracing.sampling.probability. It will be
removed in Pulse 3.0.
Java and Spring Boot version policy¶
- Java baseline moves only on a minor release and only if a mainstream LTS is End-Of-Life. 2.0 requires Java 21; CI also runs 25.
- Spring Boot minor upgrades land in Pulse minor releases when they are a no-op for consumers. A Boot major upgrade (e.g. 4 → 5) is a Pulse major upgrade.
Semantic versioning¶
Pulse follows SemVer for everything listed under "What's stable in 2.x". Purely additive changes — new feature flags, new optional properties with safe defaults, new optional SPIs — ship in minor releases.
"My build broke on a patch release"¶
Pulse patch releases (2.x.y → 2.x.(y+1)) only ship bug fixes, security
updates, and dependency bumps that don't require consumer action. If a
patch release breaks your build, open an issue
— that's a bug in the release, not your code.
See also: Concepts · Extending Pulse (SPIs) · Web stack (Servlet-only) · Configuration reference