API Stability and Backward Compatibility#

This document describes TorchFX’s commitment to API stability and backward compatibility.

Versioning Policy#

TorchFX follows Semantic Versioning 2.0.0:

MAJOR.MINOR.PATCH (e.g., 1.2.3)
  • MAJOR: Incompatible API changes

  • MINOR: Backward-compatible new features

  • PATCH: Backward-compatible bug fixes

Stability Guarantees#

What We Guarantee#

1. No Breaking Changes in Minor Versions#

Your code will continue to work when upgrading between minor versions (e.g., 1.0.0 → 1.1.0 → 1.2.0)

# Code written for 1.0.0 will work in 1.1.0 and 1.2.0
filter = LoButterworth(cutoff=1000, order=5, fs=44100)
wave = Wave.from_file("audio.wav")
filtered = wave | filter

2. Deprecation Period#

Minimum one minor version before removal

APIs will be marked as deprecated for at least one full minor version before removal in the next major version.

Version 1.0.0: Feature X introduced
Version 1.1.0: Feature X deprecated, Feature Y introduced
Version 1.2.0: Feature X still works (with warning)
Version 2.0.0: Feature X removed, use Feature Y

3. Clear Communication#

Deprecation warnings will be clear and actionable

DeprecationWarning: old_method() is deprecated since version 1.1.0.
Use new_method() instead. It will be removed in version 2.0.0.

4. Migration Support#

Documentation and migration guides for all breaking changes

  • Migration guide with step-by-step instructions

  • Code examples showing before/after

  • Rationale for changes

What We Don’t Guarantee#

Private APIs (prefixed with _) may change without notice

# Public API - Stable
from torchfx.filter import LoButterworth

# Private API - May change
from torchfx._internal_utils import some_function  # Not guaranteed

Experimental features may change until stabilized

Features marked as “experimental” in the documentation are subject to change.

Bug behavior - Bug fixes may change observable behavior

If current behavior is a bug, fixing it is not considered a breaking change.

Public API Surface#

Stable APIs (v0.5.x)#

These APIs are considered stable and will follow the versioning policy:

Top-level (torchfx)#

  • Wave - Audio waveform representation

  • FX - Base effect class

  • FilterChain - Auto-flattening sequential container (since 0.5.2)

  • is_native_available() - Native extension status check

Filters (torchfx.filter)#

  • IIR Filters:

    • Butterworth, HiButterworth, LoButterworth

    • Chebyshev1, HiChebyshev1, LoChebyshev1

    • Chebyshev2, HiChebyshev2, LoChebyshev2

    • Elliptic, HiElliptic, LoElliptic

    • LinkwitzRiley, HiLinkwitzRiley, LoLinkwitzRiley

    • Shelving, HiShelving, LoShelving

    • ParametricEQ, Peaking

  • Biquad filters:

    • Biquad, BiquadLPF, BiquadHPF, BiquadBPF, BiquadNotch, BiquadAllPass

    • Notch, AllPass

  • FIR Filters:

    • FIR, DesignableFIR

  • Filterbanks and fused cascades:

    • LogFilterBank

    • FusedSOSCascade (the fused container produced by the deferred pipeline)

Effects (torchfx.effect)#

  • Gain

  • Normalize (and its strategy classes: PercentileNormalization, CustomNormalizationStrategy, etc.)

  • Reverb

  • Delay

Validation, logging, realtime#

  • torchfx.validation — validators (validate_positive, validate_range, validate_sample_rate, validate_in_set) and exception hierarchy (TorchFXError, InvalidParameterError, InvalidRangeError, InvalidSampleRateError, InvalidShapeError, InvalidTypeError, AudioProcessingError, CoefficientComputationError, FilterInstabilityError).

  • torchfx.loggingenable_logging, enable_debug_logging, disable_logging, get_logger, log_performance, LogPerformance.

  • torchfx.realtime — streaming processor and audio backends (the sounddevice backend requires the realtime dependency group).

Parameter Stability#

Stable Parameters#

These parameter names will not change:

  • fs - Sampling frequency (Hz)

  • cutoff - Cutoff frequency for lowpass / highpass / shelving filters (Hz)

  • frequency - Center frequency for parametric / peaking filters (Hz)

  • order - Filter order

  • gain - Gain value (units selected by a sibling gain_type or gain_scale parameter)

  • q - Quality factor (lowercase, applied uniformly across all filters since 0.3.0)

Type Signature Stability#

Type signatures in stable APIs will not change in backward-incompatible ways:

# Stable signature
def forward(self, x: Tensor) -> Tensor:
    pass

# Future additions are OK (backward compatible)
def forward(self, x: Tensor, *, mode: str = "default") -> Tensor:
    pass

# This would be breaking (requires major version bump)
def forward(self, x: Tensor, required_param: int) -> Tensor:  # NOT OK
    pass

How to Check API Stability#

1. Check Documentation#

All stable APIs are marked in the documentation:

class StableClass:
    """Stable since version 1.0.0.

    This API is considered stable and will follow semantic versioning.
    """

2. Check for Deprecation Warnings#

Run your code with warnings enabled:

python -W all::DeprecationWarning your_script.py

3. Review CHANGELOG#

Check CHANGELOG.md for:

  • New features

  • Deprecations

  • Breaking changes

4. Follow Migration Guide#

See migration guide for version-specific migration instructions.

Handling Breaking Changes#

For Users#

When a breaking change is necessary (major version bump):

  1. Read the migration guide: migration guide

  2. Update incrementally: Update to latest minor version first

  3. Fix deprecation warnings: Address all warnings before upgrading

  4. Test thoroughly: Run your test suite

  5. Upgrade: Install the new major version

For Contributors#

When proposing a breaking change:

  1. Justify the change: Why is it necessary?

  2. Propose alternatives: Can it be done without breaking compatibility?

  3. Provide migration path: How will users migrate?

  4. Update documentation: Migration guide, CHANGELOG, etc.

  5. Deprecate first: Add deprecation warnings in current version

Examples#

Example 1: Adding Optional Parameters (OK)#

# Version 1.0.0
class Filter:
    def __init__(self, cutoff: float, fs: int):
        pass

# Version 1.1.0 - Backward compatible
class Filter:
    def __init__(self, cutoff: float, fs: int, order: int = 4):
        pass

# Old code still works
filter = Filter(cutoff=1000, fs=44100)  # ✅ Works in both versions

Example 2: Renaming Parameters (Breaking)#

# Version 1.0.0
class Filter:
    def __init__(self, freq: float, fs: int):
        pass

# Version 2.0.0 - Breaking change (requires major bump)
class Filter:
    def __init__(self, cutoff: float, fs: int):
        pass

# Migration path with deprecation in 1.x
# Version 1.1.0 - Add deprecation warning
class Filter:
    @deprecated_parameter("freq", version="1.1.0", alternative="cutoff")
    def __init__(self, cutoff: float = None, freq: float = None, fs: int = None):
        if freq is not None:
            cutoff = freq  # Support old parameter
        self.cutoff = cutoff

Example 3: Adding Required Parameters (Breaking)#

# Version 1.0.0
class Filter:
    def __init__(self, cutoff: float):
        pass

# Version 2.0.0 - Breaking change
class Filter:
    def __init__(self, cutoff: float, fs: int):  # fs now required
        pass

# Migration: Make it optional with deprecation in 1.x
# Version 1.1.0
class Filter:
    def __init__(self, cutoff: float, fs: int = None):
        if fs is None:
            warnings.warn("fs will be required in 2.0.0", DeprecationWarning)
            fs = 44100  # Temporary default

Contact#

Questions about API stability?