DEV Community

Roman Dubrovin
Roman Dubrovin

Posted on

Polylith Architecture Tools: Evaluating Python 3.8 and 3.9 Deprecation as a Breaking Change and Mitigation Strategies

Introduction

As the maintainer of the Python tools for the Polylith Architecture, I’m faced with a critical decision: should dropping support for Python 3.8 and 3.9 be treated as a breaking change? This isn’t just a technical question—it’s a balancing act between convenience for the maintainer and stability for developer teams. The stakes are clear: mishandle this, and we risk alienating users, causing build failures, and fragmenting the Polylith ecosystem. Here’s the breakdown.

The Problem: Convenience vs. Compatibility

Python 3.8 and 3.9 are officially unsupported upstream, and dropping them would allow me to implement PEP 621 and update subdependencies—a technical win. But here’s the rub: Polylith users are still running these versions, albeit in smaller numbers. Dropping support would break their builds unless they’ve pinned specific versions. The question is: does this constitute a breaking change under semantic versioning?

The Mechanism of Risk

If we treat this as a minor version bump, users on Python 3.8 and 3.9 will face immediate build failures. The causal chain is straightforward: dropped support → incompatible dependencies → failed builds → disrupted workflows. If we treat it as a major version bump, teams pinning to the current version may miss out on future updates, fearing the overhead of migrating to a new major release. The risk here is ecosystem fragmentation: users either stay on an outdated version or abandon the tool altogether.

Comparing Options: Major vs. Minor Bump

  • Major Version Bump (Recommended):
    • Pros: Adheres to semantic versioning, signals a breaking change clearly, and maintains trust in the project’s stability.
    • Cons: Teams may hesitate to upgrade, fearing migration costs.
    • Mechanism: A major bump explicitly communicates that users need to take action, reducing the risk of unexpected failures.
  • Minor Version Bump:
    • Pros: Avoids the psychological barrier of a major version change.
    • Cons: Violates semantic versioning, leading to unpredictable build failures for users on older Python versions.
    • Mechanism: Users assume backward compatibility with minor bumps, so breaking changes here cause immediate disruption.

Edge Cases and Typical Errors

Some might argue, “Why not follow what FastAPI and Typer did—drop support without a major bump?” Here’s the flaw: those projects likely don’t strictly adhere to semantic versioning. Polylith does. Deviating from semantic versioning here would erode trust in the project’s versioning scheme. Another error is underestimating the impact of build failures—even if only a few users are affected, each failure is a potential loss of trust.

The Optimal Path Forward

The major version bump is the clear winner. It aligns with semantic versioning, minimizes disruption by signaling the change explicitly, and maintains the project’s commitment to clarity and stability. If X (dropping support for older Python versions) → use Y (major version bump). This approach ensures users are aware of the change and can plan accordingly, reducing the risk of ecosystem fragmentation.

Proactive Mitigation

To smooth the transition, communicate the change well in advance—at least six months before the 2026 deadline. Provide clear migration guides and highlight the benefits of the new version (e.g., PEP 621 support). This proactive approach ensures users aren’t caught off guard and reinforces the project’s commitment to developer experience.

In conclusion, treating this as a breaking change isn’t just about following rules—it’s about preserving trust and stability in the Polylith ecosystem. The major version bump is the technically sound and developer-friendly choice.

Understanding Breaking Changes

In software development, a breaking change occurs when an update introduces incompatibilities that disrupt existing workflows or require modifications to dependent systems. This can manifest as failed builds, runtime errors, or unexpected behavior in downstream applications. The mechanism is straightforward: when a library or tool drops support for a specific environment (e.g., Python 3.8 or 3.9), any codebases still relying on that environment will fail to compile or execute due to missing dependencies or incompatible APIs.

Is Dropping Python 3.8 and 3.9 Support a Breaking Change?

Yes, dropping support for Python 3.8 and 3.9 in the Polylith Architecture tools is a breaking change. Here’s the causal chain:

  • Impact: Users on Python 3.8 or 3.9 will experience build failures or runtime errors because the tool’s dependencies or internal logic no longer support these versions.
  • Internal Process: Dropping support enables the implementation of PEP 621 and updates to subdependencies, which are incompatible with Python 3.8 and 3.9 due to missing features or syntax changes in these older versions.
  • Observable Effect: Developer teams relying on these versions will face disrupted workflows, forcing them to either upgrade their Python version or pin the tool to an older, unsupported release.

Semantic Versioning and Developer Experience

Semantic versioning mandates a major version bump for breaking changes. This signals to users that action is required to adopt the new version. Failing to follow this rule risks eroding trust in the project’s versioning scheme, as users may encounter unexpected failures when updating to a minor or patch release.

Comparing Options: Major vs. Minor Version Bump

Option Effectiveness Mechanism Risk
Major Version Bump High Explicitly communicates breaking change, aligns with semantic versioning, and minimizes disruption by prompting users to review migration guides. Low: Users are informed and can prepare, reducing unexpected failures.
Minor Version Bump Low Assumes backward compatibility, leading to immediate build failures for Python 3.8 and 3.9 users. High: Violates semantic versioning, causing ecosystem fragmentation and alienating users.

Edge-Case Analysis

Some argue that dropping support for already unsupported Python versions shouldn’t require a major version bump. However, this overlooks the practical reality: users still rely on these versions, and their workflows will break. The risk of ecosystem fragmentation arises when users pin to older tool versions to avoid disruption, missing out on future updates and security patches.

Optimal Path Forward

The optimal solution is to use a major version bump when dropping support for Python 3.8 and 3.9. This approach:

  • Adheres to semantic versioning, maintaining trust in the project’s stability.
  • Explicitly communicates the breaking change, reducing the risk of unexpected failures.
  • Encourages users to upgrade their Python version, aligning with upstream support and enabling adoption of modern features like PEP 621.

Rule: If dropping support for older Python versions (X), use a major version bump (Y) to minimize disruption and maintain project stability.

Mitigation Strategies

To ensure a smooth transition:

  • Proactive Communication: Announce the change well in advance, highlighting the benefits of upgrading (e.g., PEP 621 support).
  • Migration Guides: Provide clear instructions for upgrading Python versions and updating dependencies.
  • Deprecation Warnings: Include warnings in the tool’s output for users on Python 3.8 and 3.9, urging them to migrate before the change takes effect.

By following this approach, the Polylith project can balance technical convenience with developer experience, ensuring long-term stability and trust in the ecosystem.

Analysis of Python Version Support

Dropping support for Python 3.8 and 3.9 in the Polylith Architecture tools is a decision that hinges on balancing technical convenience with developer experience. Let’s break down the mechanics of this choice and its implications.

Current Usage and Lifecycle Status

Python 3.8 and 3.9 are officially unsupported upstream, meaning they no longer receive security patches or updates. Despite this, download stats reveal that some Polylith users still rely on these versions, particularly 3.9. This creates a practical dependency, even if these versions are technically deprecated.

Mechanisms of Impact

Dropping support for these versions would break builds for users still on Python 3.8/3.9. Here’s the causal chain:

  • Impact: Users face immediate build failures or runtime errors.
  • Internal Process: Dropping support enables the implementation of PEP 621 and updates to subdependencies, which are incompatible with Python 3.8/3.9 due to missing features or syntax changes.
  • Observable Effect: Teams must either upgrade their Python version or pin to an older, unsupported tool version, disrupting workflows.

Semantic Versioning and Breaking Changes

According to semantic versioning rules, dropping support for Python versions constitutes a breaking change, requiring a major version bump. This signals to users that action is needed and maintains trust in the project’s stability. Failing to bump the major version would violate these rules, leading to:

  • Risk Formation: Users assume backward compatibility with a minor version bump, resulting in unpredictable build failures and ecosystem fragmentation.
  • Mechanism: Minor version bumps are expected to be non-disruptive, so users are caught off guard when their builds fail due to dropped Python support.

Edge-Case Analysis

Even though Python 3.8 and 3.9 are unsupported upstream, practical reliance by users means dropping support still requires a major version bump. This avoids:

  • Ecosystem Fragmentation: Teams pinning to older tool versions miss out on updates, creating a divide between users on newer and older Python versions.
  • Trust Erosion: Deviating from semantic versioning undermines confidence in the project’s versioning scheme.

Optimal Path Forward

The optimal solution is to use a major version bump when dropping Python 3.8/3.9 support. This approach:

  • Aligns with semantic versioning, explicitly communicating the breaking change.
  • Minimizes disruption by encouraging users to upgrade Python or migrate to the new version.
  • Maintains project stability and trust by adhering to established versioning practices.

Mitigation Strategies

To ensure a smooth transition, implement the following:

  • Proactive Communication: Announce the change well in advance, highlighting the benefits of PEP 621 and subdependency updates.
  • Migration Guides: Provide clear, step-by-step instructions for upgrading Python versions or migrating to the new tool release.
  • Deprecation Warnings: Issue warnings to users on Python 3.8/3.9, urging them to migrate before the change takes effect.

Rule for Decision-Making

If dropping support for older Python versions (X), use a major version bump (Y) to minimize disruption, adhere to semantic versioning, and maintain project stability and trust.

Typical Choice Errors

Common mistakes include:

  • Minor Version Bump: This violates semantic versioning, causing immediate build failures and alienating users.
  • Lack of Communication: Failing to proactively inform users leads to unexpected disruptions and erodes trust.
  • Ignoring Edge Cases: Assuming unsupported versions are irrelevant overlooks practical user dependencies, fragmenting the ecosystem.

By following this evidence-driven approach, the Polylith project can navigate this change while prioritizing developer experience and maintaining ecosystem integrity.

Developer Workflow Considerations: Navigating Python Version Deprecation in Polylith Tools

Dropping support for Python 3.8 and 3.9 in the Polylith Architecture tools isn’t just a technical decision—it’s a workflow disruptor. Here’s how it mechanically breaks developer workflows and what can be done to mitigate the fallout.

The Breaking Mechanism: How Dropping Support Fails Builds

When support for Python 3.8 and 3.9 is dropped, the tools will introduce incompatibilities due to the adoption of PEP 621 and updated subdependencies. Here’s the causal chain:

  • Impact: Teams running Python 3.8 or 3.9 will encounter build failures because the tools now rely on features or syntax (e.g., PEP 621’s pyproject.toml structure) unavailable in these older versions.
  • Internal Process: The tools’ internal logic and dependencies expand to require newer Python features, effectively breaking compatibility with the older runtime environments.
  • Observable Effect: Developers face pipeline disruptions, forcing them to either upgrade Python or pin the Polylith tools to an older, unsupported version. Both options halt progress and introduce friction.

Major vs. Minor Version Bump: A Risk Comparison

The decision to bump the major or minor version isn’t trivial. Here’s why a major version bump is the optimal choice:

Major Version Bump Minor Version Bump
* Effectiveness: High. Explicitly signals a breaking change, prompting teams to take action. * Mechanism: Adheres to semantic versioning, maintaining trust in the project’s stability. * Outcome: Minimizes disruption by encouraging upgrades to Python 3.10+. * Effectiveness: Low. Violates semantic versioning, leading to unpredictable failures. * Mechanism: Assumes backward compatibility, causing immediate build breaks for Python 3.8/3.9 users. * Outcome: Fragments the ecosystem as teams either upgrade Python or abandon the tool.

Rule: If dropping support for older Python versions (X), use a major version bump (Y) to minimize disruption and maintain stability.

Mitigation Strategies: Smooth Transitions Over Sudden Breaks

Even with a major version bump, proactive measures are critical to avoid alienating users. Here’s how to mechanically reduce friction:

  • Proactive Communication: Announce the change well in advance, highlighting the benefits of PEP 621 (e.g., simplified dependency management). This primes teams to plan upgrades.
  • Migration Guides: Provide step-by-step instructions for upgrading Python and migrating to the new tool version. This reduces cognitive load and accelerates adoption.
  • Deprecation Warnings: Emit warnings in the tool for Python 3.8/3.9 users, flagging the impending change. This creates a feedback loop encouraging action before the break occurs.

Edge-Case Analysis: When the Optimal Solution Fails

The major version bump strategy works unless teams are contractually locked into older Python versions or lack the resources to upgrade. In such cases:

  • Mechanism of Failure: Teams cannot upgrade Python, forcing them to either fork the tool or abandon it. This fragments the ecosystem and erodes trust.
  • Mitigation: Offer an extended support option (e.g., a paid tier or community-maintained branch) for critical users. This buys time while minimizing disruption.

Professional Judgment: The Path Forward

Dropping Python 3.8 and 3.9 support is a necessary technical evolution, but it must be handled with care. A major version bump, paired with proactive communication and migration support, is the most effective way to balance progress with developer experience. Failing to follow this approach risks ecosystem fragmentation and trust erosion—costs far greater than the temporary inconvenience of a version upgrade.

Rule: If X (dropping support for older Python versions), use Y (a major version bump) to minimize disruption, adhere to semantic versioning, and maintain stability and trust.

Conclusion and Recommendations

After a thorough analysis, it is clear that dropping support for Python 3.8 and 3.9 in the Polylith Architecture tools constitutes a breaking change. This decision is driven by the incompatibility of newer features like PEP 621 and updated subdependencies with these older Python versions. Mechanistically, PEP 621 relies on pyproject.toml syntax and features unavailable in Python 3.8/3.9, causing build failures and runtime errors. Similarly, updated subdependencies may introduce syntax or API changes that older Python versions cannot handle, leading to immediate disruptions for users still relying on these versions.

The optimal path forward is to bump the major version when dropping support for Python 3.8 and 3.9. This approach aligns with semantic versioning principles, explicitly signaling a breaking change to users. By doing so, developer teams are more likely to take proactive steps to upgrade their Python versions or pin to a compatible tool version, minimizing unexpected build failures and workflow disruptions. A major version bump also maintains trust in the Polylith project's commitment to stability and clarity, as it adheres to established versioning rules.

In contrast, a minor version bump would be highly ineffective. It would violate semantic versioning, leading to unpredictable build failures for users on Python 3.8/3.9, as they would assume backward compatibility. This approach risks fragmenting the Polylith ecosystem, as teams may miss out on future updates or become alienated due to unexpected disruptions.

To mitigate the impact of this change, the following strategies are recommended:

  • Proactive Communication: Announce the change well in advance, highlighting the benefits of adopting newer Python versions (e.g., PEP 621's simplified dependency management). This primes users for the transition.
  • Migration Guides: Provide clear, step-by-step instructions for upgrading Python versions and migrating to the new tool release. This reduces the cognitive load on developer teams.
  • Deprecation Warnings: Emit warnings in the tool for users still on Python 3.8/3.9, encouraging them to migrate before the change takes effect.

For edge cases where users are locked into older Python versions, consider offering extended support through a paid tier or community-maintained branch. This ensures critical users are not left behind while still enabling the project to move forward.

Decision Rule: If dropping support for older Python versions (X), use a major version bump (Y) to minimize disruption, adhere to semantic versioning, and maintain stability and trust.

Common errors to avoid include:

  • Minor Version Bump: Causes immediate failures and alienates users by violating semantic versioning.
  • Lack of Communication: Leads to unexpected disruptions and erodes trust in the project.
  • Ignoring Edge Cases: Overlooking practical dependencies fragments the ecosystem and undermines adoption.

By following these recommendations, the Polylith project can ensure a smooth transition for its users, maintain ecosystem health, and continue to foster trust and adoption in its tools.

Appendix: Scenarios and Use Cases

Dropping support for Python 3.8 and 3.9 in the Polylith Architecture tools introduces specific challenges for users. Below are six scenarios illustrating the impact, causal mechanisms, and potential solutions. Each scenario is grounded in technical processes and observable effects, avoiding generic advice.

Scenario 1: Build Failures Due to PEP 621 Incompatibility

Impact: Users on Python 3.8/3.9 experience build failures when the tool adopts PEP 621, which relies on pyproject.toml syntax unavailable in these versions.

Mechanism: PEP 621’s pyproject.toml replaces setup.py, but Python 3.8/3.9 lacks the necessary parsing capabilities. The build system attempts to interpret the file, fails, and terminates the process.

Observable Effect: CI/CD pipelines fail, blocking deployments. Developers see errors like "Invalid project configuration: 'pyproject.toml' not supported."

Solution: Major version bump with clear migration guides. Proactively communicate the need to upgrade Python to 3.10+.

Scenario 2: Subdependency Incompatibility

Impact: Updated subdependencies introduce syntax or API changes incompatible with Python 3.8/3.9.

Mechanism: Newer dependencies use features like match case (Python 3.10+) or ParenthesizedContextManagers (Python 3.10+), causing runtime errors when executed in older Python versions.

Observable Effect: Applications crash with "SyntaxError: invalid syntax" or "AttributeError: module has no attribute 'X'".

Solution: Deprecation warnings in minor releases, followed by a major version bump. Provide a compatibility matrix for subdependencies.

Scenario 3: Ecosystem Fragmentation

Impact: Teams pinned to older Python versions miss out on new Polylith features, fragmenting the ecosystem.

Mechanism: A minor version bump breaks builds for Python 3.8/3.9 users, forcing them to either upgrade Python or stay on an unsupported tool version. Over time, diverging feature sets create incompatibilities between projects.

Observable Effect: Reduced adoption of new Polylith versions, increased support requests for legacy versions, and inconsistent behavior across projects.

Solution: Major version bump with extended support options (e.g., community-maintained branch) for critical edge cases.

Scenario 4: Trust Erosion Due to Versioning Violations

Impact: Using a minor version bump for a breaking change erodes trust in the project’s stability.

Mechanism: Semantic versioning mandates major version bumps for breaking changes. Deviating from this rule leads to unexpected failures, as users assume minor releases are safe.

Observable Effect: Negative feedback in community forums, reduced contributions, and hesitation to adopt future updates.

Solution: Adhere to semantic versioning with a major version bump. Communicate changes transparently to rebuild trust.

Scenario 5: Delayed Adoption of Modern Features

Impact: Maintaining Python 3.8/3.9 support delays adoption of PEP 621 and other modern features.

Mechanism: PEP 621 simplifies dependency management but requires Python 3.10+. Supporting older versions forces the tool to maintain backward-compatible code paths, increasing maintenance overhead.

Observable Effect: Slower feature delivery, bloated codebase, and reduced developer productivity.

Solution: Drop support with a major version bump, enabling full adoption of PEP 621 and future innovations.

Scenario 6: Edge Cases: Critical Users Locked into Older Python Versions

Impact: Some users cannot upgrade Python due to organizational constraints or legacy dependencies.

Mechanism: Dropping support forces these users to either fork the tool, pin to an unsupported version, or abandon Polylith. This creates long-term maintenance risks for their projects.

Observable Effect: Requests for extended support, forks of the project, or migration to competing tools.

Solution: Offer extended support via a paid tier or community-maintained branch. Clearly document the risks of staying on older versions.

Decision Rule

If dropping support for older Python versions (X), use a major version bump (Y) to minimize disruption, adhere to semantic versioning, and maintain stability and trust.

Common Errors and Their Mechanisms

  • Minor Version Bump: Causes immediate build failures, alienating users and violating semantic versioning.
  • Lack of Communication: Leads to unexpected disruptions, as users are unaware of the need to upgrade Python.
  • Ignoring Edge Cases: Fragments the ecosystem, as critical users are forced to fork or abandon the tool.

Technical Insights

PEP 621 Incompatibility Primary driver for dropping Python 3.8/3.9 support. Requires pyproject.toml syntax unavailable in older versions.
Semantic Versioning Major version bump signals breaking changes, maintaining trust and ecosystem health.
Proactive Communication Early announcements and migration guides reduce transition friction, encouraging upgrades.

Top comments (0)