Skip to content

API breaks are not for free #3166

@darosior

Description

@darosior

The rust-bitcoin project has been pretty reckless with API breaks. This trend started about a couple of years ago. API breaks introduce costs and risks to downstream projects. Some of these projects are used in production. I believe as Bitcoin developers we should strive to minimize the risk to end users' money. Here i will argue most API breaks (sometimes even justified on vague "safety" rationale) since this trend started have effectively be, on balance, a net-negative to the safety of end users' funds.

First of all let me be clear that i do not claim API breaks should never happen. There may be good reasons for them. My point is there should be good reasons for them to happen.

Also, please appreciate how there is a dispersed cost of the code churn to all users of the library, whereas people actively following developments may be less impacted (and more inclined to take advantage of the benefits brought up by the changes). As such, readers of this issue (who are part of the latter group) may overestimate the benefits and underestimate the costs. For this reason i also don't think my projects are those most impacted. The large majority of impacted downstream maintainers would not bother working on a structured and justified writeup advocating for less API breaks. They would just patch the breaks mechanically (and sometimes incorrectly) or just not upgrade at all.

You are well aware of the potential gains from changes which necessitate an API break. Let me layout the costs. I can think of 3 main categories:

  1. Code churn increases the likelihood of introducing bugs. The rust-bitcoin crate is a low level library core to a lot of Bitcoin projects written in Rust. Breaks of its API induce large refactorings in downstream projects. Refactorings, especially large ones, and especially of core parts of the software, risk introducing behaviour discrepancies with unintended consequences.
  2. Opportunity costs. Besides the risk of defects, such large refactorings introduce maintenance burden: both for the developer writing the code and the one(s) reviewing it. This time could be affected to developments with higher impacts on the safety/security of end users than refactoring half the codebase because a core type was made "safer" by upstream and can't be used the same way anymore.
  3. Overly complexified API for "safety" purpose gets bypassed. Related to the second point around costs, if the refactoring is too involved the user might aim for the simplest patch that compiles (thereby introducing bugs, again) or just opt out of using the types altogether.

These have led to the introduction of bugs and people not upgrading anymore: 72% of rust-bitcoin downloads at crates.io this month are for releases older than 5 versions back, and only 12% are for any of the last 4 releases. Of course people not upgrading means they don't benefit from bug fixes, which is another safety cost to take into account.

To substantiate my claim, here is a list of some past refactorings for which i believe the cost of the API break outweighed its benefits.

First of all a few instances of "let's break the API because this is more idiomatic / feels nicer":

Another interesting instance is #1489, which introduced massive refactorings for downstream projects and ended up creating at least a couple bugs i'm aware of because of points 1) and 3) above. Which is ironic, as the change was motivated by "safety" reasons.

Let me finish by mentioning this frustration has also been expressed by several developers in the industry. I hope they'll chime in and further support our case by sharing their own experience.

Could the rust-bitcoin project become more conservative with regard to API breaks? Thank you all for your work on maintaining and bettering this great library, i hope you'll take my feedback into consideration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions