Skip to content
96 changes: 96 additions & 0 deletions develop-docs/sdk/processes/breaking_changes.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Breaking Changes
description: Learn about our principles and processes when it comes to introducing breaking changes.
sidebar_order: 4
---

Code ages, features and APIs become obsolete. All of this is expected when working on a library for an extended period of time. Deciding what to drop, how, and when, is not straightforward. Our wishes as developers to evolve a codebase inevitably clash with the user experience of the folks using it.

At Sentry, user experience is a core part of our [SDK development values](/sdk/philosophy). Evolving our SDKs is ultimately a balancing act between what we as engineers think is right (for us, for the health of the codebase, and for the users), and the ease of use on the user side.

This page aims to provide a basic set of guidelines how to think about this topic, to help drive discussions, and ultimately empower SDK engineers to make good decisions.

Dealing with breaking changes (or even deciding what is one) is by no means an easy problem with a clear-cut solution, so discussing on a case-by-case basis with your teammates is always a good idea and very much encouraged.


## Changes to Be Mindful Of

Is something a change that should go out in a major release? Answering this question is often the hardest part of the process. Going strictly by semantic versioning rules, where we simply evaluate whether the API has undergone a backwards-incompatible change, doesn't cover all cases where we might be significantly altering a user's experience using Sentry.

In general, changes that the user needs to adapt to or changes that significantly alter the behavior of the SDK require scrutiny.


### SDK API Surface Changes

The most obvious kind of breaking changes is changing the way the user interacts with the public API of the SDK, for instance:
- Dropping or renaming part of the API
- Dropping or renaming an argument to an API function
- Changing the type of an argument to an API function and not accepting the previous type anymore

In some SDKs, the line between public and private API is unclear. If unsure, discuss with your teammates. Some pointers:
- Is the API mentioned in the user-facing docs? Then it's probably public and you should consider making changes to it in a major release.
- Was the code you're changing solely created for an internal purpose? Is it a utility function, or a helper function we added to make testing easier? Then it's fine to change.
- Can you reasonably assume a significant portion of the user base is using this?

Naturally, the language of your SDK and the community around it also affects what is generally considered a breaking change. Some languages provide their own guidelines:
- [.NET](https://learn.microsoft.com/en-gb/dotnet/core/compatibility/library-change-rules)


### Changes in the Product

We also need to be mindful of what the SDK change might cause in the product. Sometimes we're forcing users to make changes in their use of Sentry because we, for example, broke a dashboard by renaming a span attribute. However, we also don't want to be in a position where we can't fix an attribute name without releasing a new major version of the SDK. Having to adopt a new major version every month is also not great UX.

In general, we consider changes to the following product-side features potentially problematic:
- **Grouping:** An SDK change might result in error events being grouped differently, because we remove, add or change some of the data on the event that is used in the grouping algorithm on the server. When you think a change might affect grouping, it's recommended to try the change yourself and check in Sentry to see if grouping is preserved.
- **Dashboards:** A user has set up a dashboard that filters on specific data and we change that data. For instance, changing a span's `op` might mean a dashboard showing those spans will be empty after an SDK update.
- **Alerts:** Alerts might stop firing because we've changed an attribute.

Changes to grouping, dashboards and alerts need closer inspection. In order to make a good decision, you can try to estimate how many users are affected using our data analytics tools. It always needs a human/team to weigh in.


#### Gauging the Impact in the Product

In order to gauge the impact of the change, you can consult internal stats on how many alerts or dashboards are using the specific property:
- You can reach out to the Data team.
- If you have Redash access (which you can request via the IT helpdesk), you can execute the queries yourself. The easiest way to do this is:
- Find an example dashboard that looks similar to what you need (for instance, [this dashboard](https://redash.getsentry.net/dashboards/372-span-status-usage-in-widgets-and-alerts) can be adapted for checking span-related alerts)
- Navigate to a specific widget on the dashboard, open the dropdown menu and click on `View Query`
- Fork the query on the top right
- Modify as you need and execute

If you find out only a small number of users is using the attribute you're about to change, you can consider releasing it in a minor version and reaching out to the folks affected directly. The Support team will be able to help.

The caveat to gauging impact this way is that self-hosted Sentries are not included. However, it still provides a good baseline: attribute usage stats on SaaS are unlikely to be vastly different from those on self-hosted.


### SDK Behavior Changes

There are also changes that technically don't require the user to adapt, but they might impact their UX significantly. These tend to be subtle and often need to be evaluated on a case-by-case basis. Be especially mindful of:

- Changes that affect the user's quota. The SDK might, for instance, start sending much more spans because we auto-enabled an integration or changed an option from opt-in to on by default.
- Changes that might result in events being dropped. We might, for instance, increase or remove a default trimming limit in the SDK, which might result in payloads big enough that they are rejected during ingestion.


## Introducing Breaking Changes

So you're considering introducing a breaking change. How can you do this in a way that's least painful for the users?

Some of this is, again, dependent on your SDK's language. Some language communities are generally more open to new majors, while in others you can expect that introducing a new major release will mean folks will be less likely to upgrade.

In any case, introducing a new major release creates friction. The harder it is to upgrade, the less people will actually do it. We want to minimize the number of folks staying on old releases because upgrading is too much of a hassle for them.

Fortunately, there is always a lot you can do (and not do) to make the upgrade process smoother.

### Factors Increasing Friction

- Piling up breaking changes. Especially if you don't have major releases often, you might be tempted to queue a lot of breaking changes into one release.

### Ways to Lessen Friction

- Call-outs in relevant places in the docs and in the changelog.
- Deprecation warnings that a breaking change is coming.
- Supporting an intermediate period where both the old and the new way of doing things works.
- A polished migration guide with a lot of easily copy-pastable before-and-after examples.
- Trying to do the upgrade yourself on a test app. Instruct an LLM to do the update using your migration guide and see how well it works.
- Providing a tool that helps with the upgrade, for example using codemods.
- Maintain deprecated APIs, if possible, for another major version.
Loading