-
Notifications
You must be signed in to change notification settings - Fork 40
Feature-Driven Releases & API Versioning #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
WhitWaldo
wants to merge
3
commits into
dapr:main
Choose a base branch
from
WhitWaldo:release-process
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
# Evolving Dapr's API and Release Strategy | ||
Author: @whitwaldo | ||
|
||
## Overview | ||
This proposal introduces a new approach to how Dapr defines, evolves, and releases its APIs and runtime features. It | ||
recommends moving away from a rigid, | ||
[calendar-based release cycle](https://github.com/dapr/community/blob/master/release-process.md#release-cycle-and-cadence) | ||
in favor of a feature-driven release model and adopting semantic versioning for all APIs. These changes aim to improve | ||
the quality and predictability of releases, reduce pressure on contributors, and enable better coordination across the | ||
runtime, SDKs, components, and documentation. | ||
|
||
By decoupling release timing from the calendar and aligning SDKs with explicitly versioned APIs, this model fosters | ||
a more sustainable development process. It empowers contributors to focus on delivering well-designed, well-reviewed | ||
features — released when they’re truly ready — while improving the developer experience and trust in the platform. | ||
|
||
## Background | ||
Dapr currently follows a quarterly release cadence, with each release bundling new features, bug fixes, and updates | ||
across the runtime, SDKs, and components. APIs are labeled as `alpha`, `beta`, or `stable`, with the assumption that | ||
`stable` APIs are locked in shape but may receive additive changes. | ||
|
||
In practice, this model has led to several challenges: | ||
- **Misaligned expectations**: The term "stable" is often misunderstood as a signal of feature maturity or reliability, | ||
rather than API immutability. | ||
- **Late-stage changes**: Features are frequently added late in the release cycle, bypassing the proposal process and | ||
leaving SDKs will little time to adapt. | ||
- **SDK lag and inconsistency**: The SDKs can struggle to keep up with the runtime changes, especially when APIs are | ||
still developing late in the release cycle. | ||
- **Release drift**: The project has consistently missed its self-imposed 3-month release targets, sometimes by multiple | ||
months, creating stress and undermining confidence in the process. | ||
|
||
| Version | Release Date | Drift from Last Release | | ||
|---------|--------------|-------------------------| | ||
| 1.10 | 2/16/23 | - | | ||
| 1.11 | 6/12/23 | +1 month | | ||
| 1.12 | 10/11/23 | +1 month | | ||
| 1.13 | 3/5/24 | +2 months | | ||
| 1.14 | 8/14/24 | +2 months | | ||
| 1.15 | 2/27/25 | +3 months | | ||
| 1.16 | Jul/Aug 2025 | +2-3 months | | ||
|
||
These issues have made it harder for contributors to collaborate effectively and for developers to trust that new features | ||
are ready for production use. This proposal addresses those concerns by introducing a more deliberate, versioned, and | ||
decoupled release model - one that supports both innovation and stability. | ||
|
||
## Proposed Changes | ||
### 1. Adopt Feature-Driven Releases | ||
- Replace the current calendar-based release cycle with a feature-driven release model. | ||
- Under this new model, a new minor version of the runtime and components is published only when a feature is complete - | ||
meaning it has gone through the full lifecycle of proposal authorship, design, implementation, testing, and documentation. | ||
- Bug fixes and security patches will continue to be released as patch versions from the most recent minor release. | ||
|
||
#### Why? | ||
- This will reduce pressure on contributors to rush features into a release window, which can lead to incomplete | ||
designs, insufficient testing, or skipped documentation. | ||
- It improves quality by allowing each feature to take exactly as much time as it needs - no more, no less. | ||
- It encourages thoughtful planning and prioritization, since features are released when ready, not when the calendar | ||
demands it. | ||
- This aligns with real-world development: In practice, many features already miss the intended release window and are | ||
added late in the cycle, often without a comprehensive review. This change formalizes a more sustainable and realistic | ||
approach. | ||
|
||
### 2. Use Semantic Versioning for APIs | ||
- Eliminate the current `alpha`, `beta`, and `stable` labels for APIs and instead adopt semantic versioning for each | ||
building block's API. | ||
- Each API will have its own version number, independent of the runtime version: | ||
- **Major version**: Introduces breaking changes to existing endpoints | ||
- **Minor version**: Adds new, backward-compatible functionality | ||
- **Patch version**: Not applicable to APIs (reserved for runtime/component bug fixes or SDK improvements) | ||
|
||
#### Why? | ||
- Clarifies expectations because developers can immediately understand the scope of the changes by looking at the | ||
version number. | ||
- Improves communication as it resolves ambiguity around what "stable" means and replaces it with a well-understood | ||
industry standard. | ||
- It supports incremental evolution because APIs can grow and improve without needing to wait for a major runtime release. | ||
- Versioned APIs make it easier to generate accurate SDK, documentation, and compatibility matrices enabling better tooling | ||
and documentation. | ||
- It prevents stagnation and avoids the trap of APIs becoming "frozen in time" once marked stable. Semantic versioning | ||
allows for continued evolution while maintaining backward compatibility guarantees, encouraging innovation without fear | ||
of breaking existing users. | ||
|
||
### 3. Independently Version HTTP and gRPC APIs | ||
- Allow the HTTP and gRPC interfaces for each building block to be versioned independently. | ||
- While we still have a goal of functional parity between the two, this change acknowledges that certain features may | ||
be more naturally suited to one protocol over the other. | ||
|
||
#### Why? | ||
- **Supports protocol-specific innovation**: Some capabilities may be easier or more efficient to implement in gRPC than | ||
HTTP (or vice versa), and this model allows for that flexibility. | ||
- **Avoids unnecessary coupling**: Changes to one protocol's API don't need to block or delay progress on the other. | ||
- ** Minimal disruption**: Since most SDKs already prefer to target the gRPC APIs - using HTTP only as a fallback - this | ||
change does not require significant rework. It simply formalizes a pattern that is already widely followed. | ||
|
||
### 4. Runtime Support for API Versioning | ||
- The Dapr runtime should support multiple versions of each building block's API simultaneously - ideally, the latest | ||
version and at least the two prior minor versions (i.e., **N**, **N-1**, **N-2**). | ||
- This versioning should apply independently to each building block and protocol (gRPC and HTTP), allowing them | ||
to evolve at their own pace without forcing synchronized upgrades across the entire system. | ||
- When a new API version is introduced, the runtime should: | ||
- Continue to serve older versions for backward compatibility | ||
- Route requests based on the version specified in the request (e.g. via header or query string or metadata for gRPC). | ||
- Clearly document which versions are supported and when they are scheduled for deprecation or removal. | ||
|
||
#### Why? | ||
- **Predictable Compatibility**: Developers can confidently build against a specific API version, knowing it will be supported | ||
for a defined period | ||
- **Decoupled Evolution**: Building blocks can evolve independently, reducing the need for large, coordinate changes | ||
across the runtime and SDKs | ||
- **Improved Developer Experience**: Developers can adopt new features at their own pace, without being forced to upgrade | ||
to the latest runtime or SDK version immediately | ||
- **Foudation for Modular Runtime**: This model lays the groundwork for a future where the runtime itself could adopt a | ||
more modular architecture - potentially versioning and releasing building blocks independently, just as some SDKs do. | ||
|
||
This versioning strategy ensures that the runtime becomes a stable, flexible platform for innovation - one that supports | ||
both rapid iteration and long-term reliability. | ||
|
||
### 5. SDKs Target Specific API Versions | ||
- SDKs should explicitly target and implement only released versions of each building block's API. | ||
- Each SDK should document which versions of each API it supports, and ideally stay within one minor version of the latest | ||
available API version. | ||
- SDKs can be versioned independently of the Dapr runtime, reflecting their own release cadence and the specific APIs | ||
they support. | ||
|
||
#### Why? | ||
- **Improves reliability**: Developers using SDKs can trust that the functionality exposed is stable, supported, and | ||
well-documented. | ||
- **Decouples SDK and runtime timelines**: There is no longer any pressure to ship updates in lockstep with runtime | ||
releases, especially when APIs are still evolving. | ||
- **Supports modular packaging**: SDKs can adopt building-block-specific packages (e.g. how .NET has Dapr.Workflows, | ||
Dapr.Actors, Dapr.Jobs, etc.) that align with the versioning of the APIs they wrap. This allows for more granular | ||
updates, and better dependency management. | ||
- **Enables preview isolation**: SDKs may optionally offer preview packages for unreleased APIs (e.g. version 0.x APIs), | ||
clearly signaling their experimental nature and avoiding confusing with stable releases. | ||
- **Aligns with real-world usage**: Many SDKs already operate semi-independently of the runtime version (e.g., the | ||
- JavaScript SDK uses a different major versioning scheme). This proposal formalizes and supports this flexibility. | ||
|
||
## Impact on Runtime | ||
- **Asynchronous Development**: The runtime team is no longer constrained by SDK timelines or calendar deadlines. Features | ||
can be developed, reviewed, and released when they are ready - not when the calendar says they must be. | ||
- **Proposal-First Culture**: With versioned APIs and feature-driven releases, every change - large or small - must go | ||
through the full proposal lifecycle. This ensures that all features receive appropriate design scrutiny, documentation, | ||
and testing before release. | ||
- **Simplified Compatibility Model**: Supporting multiple API versions (e.g N, N-1, N-2) allows the runtime to evolve | ||
without breaking existing integrations. This makes it easier to introduce new capabilities while maintaining trust with | ||
users. | ||
- **Foundation for Modularity**: Just as SDKs can benefit from modular packaging and independent versioning, this model | ||
lays the groundwork for the runtime to eventually do the same - enabling more targeted updates and clearer ownership | ||
boundaries across building blocks. | ||
- **Improved Developer Experience**: Developers interacting with the runtime will have a clearer understanding of what's | ||
supported, what's changing, and how to adopt new features - all without surprises or regressions. | ||
- Moving away from calendar-based releases also builds developer trust and confidence that a feature is truly ready | ||
when it ships, rather than being rushed to meet a deadline. | ||
- It avoids the negative optics and morale impact of repeatedly missing scheduled release windows, which can erode | ||
confidence in the release process and the stability of new features. | ||
- **Enhanced Communication Opportunities**: With more frequent, feature-driven releases, the project gains flexibility | ||
in how it communicates progress: | ||
- Major features can be highlighted in dedicated blog posts or announcements, given them the spotlight they deserve | ||
- The community team could maintain a quarterly recap of all changes across the runtime, components, SDKs, and | ||
documentation - regardless of release timing. | ||
- Either approach should continue to recognize and celebrate contributors to each feature, which may require new tooling | ||
to better track contributions across modular releases - but offers a valuable opportunity to strengthen community | ||
engagement and visibility. | ||
|
||
## Impact on SDK Maintainers | ||
- **Clear Implementation Boundaries**: SDKs will only implement features from officially released API versions, eliminating | ||
the ambiguity and churn caused by evolving or unstable APIs. | ||
- **Independent Release Cadence**: SDKs can release updates on their own schedules, aligned with the APIs they support - not | ||
the runtime's minor version. This is especially beneficial for SDKs that already use independent versioning schemes. | ||
- **Support for Modular Packaging**: SDKs can adopt building-block-specific packages (e.g. Dapr.Workflows, | ||
Dapr.Actors, Dapr.Cryptography), each versioned according to the API it supports. This enables more focused development, | ||
testing, and release workflows. | ||
- **Improved Documentation and Transparency**: By clearly documenting with API versions are supported, SDKs can provide | ||
a more predictable and trustworthy experience for developers. | ||
- **Optional Preview Support*: SDKs may choose to support unreleased APIs via preview packages (e.g. for v0.x APIs),but | ||
this is opt-in and clearly separated from stable releases - reducing risk and confusion. | ||
|
||
## Next Steps | ||
To ensure a smooth transition and avoid immediate versioning confusion across the ecosystem, the following steps are | ||
recommended upon acceptance of this proposal: | ||
|
||
1. Baseline all existing APIs at v2.0 | ||
All currently released APIs should be versioned as **v2.0** to establish a clean starting point for semantic versioning. | ||
This ensures that SDKs - particularly those that currently align their versioning with the Dapr runtime - are not | ||
immediately out of sync and can adopt the new model without disruption. | ||
2. Update SDKs to reflect API versioning | ||
SDK maintainers should begin updating their packages to reflect the specific API versions they support. This may include: | ||
- Updating documentation to indicate supported API versions | ||
- Refactoring SDKs into modular packages (where applicable) to align with building block versioning | ||
- Planning for preview/experimental packages for unreleased APIs (e.g. v0.x) | ||
- Updating build and release pipelines to support independent versioning and publishing of modular SDK packages, enabling | ||
more granular and maintainable release workflows. | ||
3. Update Runtime to Support API Version Routing | ||
The runtime should begin implementing support for versioned API routing and compatibility (e.g. N, N-1, N-2 support and | ||
identifying how the version should be communicated, e.g. query string or header for HTTP, metadata for gRPC). | ||
4. Move quickly ahead of 1.17 planning | ||
This proposal should ideally be accepted prior to the 1.17 release planning cycle, so that the new model can be piloted | ||
immediately rather than continuing under the current calendar-based approach. Once accepted: | ||
- The mechanics of API version signaling (e.g. whether the version if passed via query string or header for HTTP, | ||
confirmation that use of metadata in gRPC) should be finalized and documented. | ||
- Each existing API should be formally released and documented as version 2.0, establishing a clear baseline for | ||
semantic versioning going forward. | ||
- During this transition period - and indefinitely going forward until v2.0 is deprecated under the project's backwards- | ||
compatibility policy (e.g. N, N-1, N-2) - if a client does not explicitly specify an API version, the runtime should | ||
assume the request targets v2.0. This ensures a smooth migration path for existing users and provides a stable default | ||
for new integrations. | ||
|
||
## Conclusion | ||
This proposal is shared with the goal of empowering Dapr maintainers and contributors to collaborate more effectively, | ||
reduce unnecessary stress, and deliver higher-quality features. By moving away from rigid, calendar-based release cycles | ||
and embracing a feature-driven, semantically versioned model, we create space for thoughtful design, thorough testing, | ||
and meaningful documentation - all without the pressure of arbitrary deadlines. | ||
|
||
These changes are not about slowing down progress, but about ensuring that progress is sustainable, deliberate, and inclusive | ||
of the entire ecosystem. When features are released only when they're truly ready - and when ever change receives the | ||
attention it deserves - we build trust with our users, reduce technical debt, and make it easier for all contributors | ||
to work in sync. | ||
|
||
Ultimately, this proposal is about enabling the Dapr project to scale with clarity and confidence, while continuing to | ||
deliver powerful, reliable capabilities to the developers who depend on it. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how would you forsee this impacting component statuses of alpha, beta, stable?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose eliminating them and replacing with semantic versioning. Beta doesn't ever seem to be used as we're in this rush to indicate a "stable" API (in shape, not necessarily in platform stability) and then when new endpoints are added to stable APIs, they're sort of in this weird flux of not really being stable (since it just changed) but we also don't move a stable API back to alpha, so it really doesn't work well.
As I indicate in the document, by opting to instead use semantic versioning, we can hold ourselves to a position where we release an API as 1.0 when we're happy with an initial release. Additive methods simply iterate the minor version (as they don't break existing implementations that aren't aware of the new methods) and if we must change an existing endpoint or remove it, that constitutes a new major version. But as semantic versioning is otherwise very well understood by the developer community, this eliminates the vagueness of our existing API lifecycle, allows us to keep incrementally iterating on the APIs as needed and doesn't lock us into getting stuck with an API that could have been better designed just because "well, it's the one we declare stable, so we have to stick with it".
In terms of immediate effects, I would replace all stable APIs with a
v2.0
version and all APIs in alpha and beta withv0.1
and iterate from there as much as necessary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha - makes sense and i agree! any reason for a v2.0 instead of v1.0 for stable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly just to have a clear distinction in the versioning between what we use today and the new versioning. Most everything in Dapr is marked as v1 with some lifecycle tag, e.g. "v1-alpha", so by jumping to v2.0, it's more symbolic that the major change is that the entire versioning scheme is being overhauled at this point.