Skip to content

Compatibility and guarantees

This page identifies the behavior Radixor supports as public, the internals that may evolve, and the upgrade checks required across versions. Model artifact and format version axes are documented in Stemmer Models and Radixor Data Formats; support and vulnerability reporting belong to Trust, Security and Support.

Supported release policy

The public project supports the latest published release of each runtime. Older releases are supported only under a separate contract.

The major number identifies major change affecting the project as a whole; the minor number identifies a shared fix or improvement affecting all runtimes. Patch numbers belong to each runtime's own fix and improvement stream, so Java, PyO3 and Python-C patch versions may differ. Model and model-catalog versions evolve independently. See Trust, Security and Support for the support and private vulnerability-reporting channels.

Compatibility philosophy

Radixor distinguishes the supported library contract from implementation details that may evolve.

At the same time, the project distinguishes clearly between:

  • public API and behavior that users are expected to build against,
  • internal implementation layers that may change more freely when needed for correctness, performance, or maintainability.

The practical policy is straightforward:

  • keep the main user-facing API in org.egothor.stemmer stable and supportable,
  • allow more freedom of evolution in internal trie-focused implementation layers,
  • extend the project conservatively without creating unnecessary behavioral ambiguity.

Public API posture

As a general rule, the org.egothor.stemmer package should be treated as the primary supported API surface.

That includes the main user-facing types involved in:

  • dictionary loading,
  • binary loading and persistence,
  • patch-command application,
  • compiled trie querying,
  • reconstruction workflows,
  • reduction configuration,
  • CLI use.

This API is the supported integration surface. Compatibility changes favor additive evolution: documentation can become more precise and capabilities can be added without invalidating established usage.

Examples of additive evolution include:

  • additional independently versioned language models,
  • fuller support for diacritics or native-script language resources,
  • expanded documentation and operational tooling,
  • new convenience methods that do not break existing code.

Internal API posture

The org.egothor.stemmer.trie package should be treated as internal or at least significantly less stable implementation API.

It represents the structural machinery behind mutable nodes, reduced nodes, compiled nodes, reduction context, signatures, and related internal compilation details. These types may evolve more aggressively when needed to improve implementation quality, correctness, reduction behavior, internal representations, or performance characteristics.

Users should therefore avoid building long-term integrations against org.egothor.stemmer.trie unless they are intentionally accepting that tighter coupling.

In practical terms:

  • org.egothor.stemmer is the supported integration layer,
  • org.egothor.stemmer.trie is the implementation layer.

Behavioral guarantees

Several project properties are intended as core behavioral guarantees.

Deterministic dictionary loading and compilation

Given the same textual dictionary input and the same reduction settings, Radixor produces the same compiled stemming semantics reproducibly.

This includes deterministic local result ordering and deterministic observable lookup behavior.

Stable meaning of get() and getAll()

The distinction between preferred-result lookup and multi-result lookup is part of the supported behavior model.

  • get() returns the locally preferred stored value,
  • getAll() returns all locally stored values in deterministic ranked order,
  • getEntries() returns aligned values with counts.

That model is part of how the public API should be understood.

Visitor lookup methods such as getAllNormalized(..., EntrySink, maxResults) are additive hot-path APIs. They expose the same local ordering and count semantics without allocating result containers, but they do not replace get(), getAll(), or getEntries().

Compiled FrequencyTrie instances are immutable and thread-safe for concurrent reads. Visitor sinks are caller-owned and are not retained by the trie. Stored values passed to sinks are the model-owned trie values; for FrequencyTrie<String> patch tries, those patch strings are immutable stored strings rather than fresh per-result strings.

Stable patch application behavior

Serialized patch-command strings remain the stable stored representation used by textual dictionaries and binary artifacts. Runtime stemming should use CompiledPatchCommand values produced by StemmerPatchTrieLoader.loadCompiled(...), StemmerPatchTrieLoader.loadBinaryCompiled(...), or PatchCommandEncoder.compile(...).

Language-default, descriptor, and stable model-ID loadCompiled entry points share the same compiled-value conversion. Explicit model IDs never fall back to a language default. Model loading is not cached, and construction-memory requirements are model-dependent; the unusually large PoliMorf input is verified separately with a 6 GiB maximum heap.

The historical PatchCommandEncoder.apply(...) and String-based applyTo(...) overloads remain compatibility APIs during the 2.x transition, but they are deprecated because they reparse the patch-command string on each application. See Migration and Backward Compatibility for old and new code examples.

Compiled buffer-oriented CompiledPatchCommand.applyTo(...) overloads use caller-owned output storage. They do not retain output arrays and report insufficient capacity with CompiledPatchCommand.APPLY_INSUFFICIENT_CAPACITY.

Stable reduction-mode intent

Each public ReductionMode constant carries a semantic contract that should remain meaningful across versions.

In other words, the implementation may evolve, but the intended meaning of modes such as ranked getAll() equivalence, unordered getAll() equivalence, and dominant get() equivalence should not drift casually.

Internal pre-reduction optimizations may still change the physical compiled trie shape when they preserve the documented lookup contract. Uniform-subtree contraction is one such optimization: it can replace a subtree with an accepting leaf when all reachable entries choose the same preferred patch command.

Stable binary artifact purpose

Compiled .radixor.gz artifacts are a first-class project output. Loading and persisting compiled stemmer artifacts is part of the intended usage model, not an incidental implementation side effect.

What is allowed to evolve

Compatibility does not mean the project is frozen.

The following kinds of change are generally compatible with the project’s direction:

  • improved internal data structures,
  • changes inside org.egothor.stemmer.trie,
  • expanded model dictionaries,
  • additional supported languages,
  • improved native-script handling,
  • better benchmarks, tests, and reports,
  • additive public API growth that does not invalidate existing usage.

The project should be able to improve substantially while keeping the main user-facing integration model intact.

What may change more cautiously

Some areas should be treated as stable in intent but still approached carefully when changed.

Independently versioned model contents

Model resources are independently versioned project data, not immutable language standards. Their contents may improve over time.

That means stemming outcomes can legitimately change when a model artifact is updated. Such changes are separate from core compatibility and should be reviewed as lexical-resource behavior changes.

Binary format evolution

Compiled binary artifacts are a supported project output, while the versioned binary format may evolve.

If the format changes, that should be handled deliberately and documented clearly. Users should not assume that every historical persisted artifact will remain readable forever without versioning considerations. What should remain stable is the project’s support for compiled artifact workflows, not necessarily perpetual cross-version binary interchange without explicit format evolution rules.

Performance characteristics

Radixor places strong emphasis on performance, but no benchmark number should be treated as a formal compatibility guarantee.

No single raw number defines the performance contract. The relevant architectural property is a compact compiled stemmer whose throughput is measured under documented workloads.

What users should rely on

Long-term users should rely primarily on the following:

  • the main integration path in org.egothor.stemmer,
  • the documented meaning of get(), getAll(), and reduction modes,
  • the offline-compilation plus runtime-loading workflow,
  • the availability of compiled artifact support,
  • the project’s preference for deterministic and auditable behavior.

These are the project's stable, supported integration boundaries.

What users should not rely on casually

Users should avoid depending on:

  • internal trie package details,
  • undocumented internal classes or intermediate representations,
  • incidental internal ordering outside documented lookup semantics,
  • assumptions that a model's dictionary contents will never evolve across model versions,
  • assumptions that internal binary-format details are frozen forever.

If a behavior is important to your integration, it should ideally be documented at the public API or project-documentation level rather than inferred from internal implementation details.

Source compatibility and behavioral compatibility

It is useful to distinguish two different notions of compatibility.

Source compatibility

Whether existing Java code using the supported public API still compiles and integrates cleanly after an upgrade.

Behavioral compatibility

Whether the upgraded system still behaves the same way for the same dictionary data, compiled artifacts, and runtime calls.

Radixor preserves both within the documented compatibility boundary, but dictionary refinement and correctness fixes can intentionally change behavior. Evaluate upgrades as both code changes and stemming-behavior changes.

When upgrading Radixor in a production environment, it is good practice to:

  1. review release notes and documentation changes,
  2. rebuild compiled artifacts if the upgrade affects dictionary or artifact handling,
  3. rerun representative stemming validation tests,
  4. compare benchmark outputs where performance matters,
  5. inspect whether bundled-dictionary changes affect expected canonical results.

This is especially important for deployments that treat stemming behavior as part of search relevance or normalization policy.

Summary

Radixor’s compatibility model is intentionally layered.

  • org.egothor.stemmer should be treated as the supported public integration API,
  • org.egothor.stemmer.trie should be treated as an internal implementation layer,
  • deterministic public behavior and compiled-artifact workflows are core project commitments,
  • internal structure and lexical-resource quality can continue to evolve.

This model gives the project room to improve while still providing a reliable surface for long-term use.