docs/release_notes/v1.18.0.md
We're excited to announce the release of Dapr 1.18! This is primarily a Workflows release, focused on security, durability, and scale. Workflow history can now optionally be cryptographically signed and verified on every state load, so tampering is caught the moment state is read. The same protection extends across application boundaries: child workflow and activity completions are attested between apps. A new WorkflowAccessPolicy resource controls which application IDs may invoke which workflows and activities. Workflows can also propagate slices of their history to the children they schedule, letting a child act on upstream context instead of reading it back from a state store. And the Scheduler gained global and per-name concurrency limits that cap how many workflows or activities run at once across the cluster.
Outside of Workflows, the Jobs API graduates to stable, hot-reloading of components and other resources is now GA and on by default, and the sidecar injector understands Kubernetes native sidecar containers. This release also introduces a new MCPServer resource that exposes Model Context Protocol tool calls as durable Dapr Workflows. Several changes make the control plane steadier under load: an opt-in coalesce window collapses redundant placement dissemination rounds during large scale-ups, placement and scheduler support hard anti-affinity, host resolution now works over IPv6 and dual-stack, and pub/sub drains in-flight messages on graceful shutdown instead of dropping them.
Before you upgrade, note one change in Sentry. It now generates workload identity keys using Ed25519 instead of ECDSA. This is invisible on a fresh install or a normal upgrade, but it means you cannot safely roll back below 1.17.7. See the new Downgrading section for the safe rollback path.
Thanks to all the new and existing contributors who helped make this release happen.
If you're new to Dapr, visit the getting started page and familiarize yourself with Dapr.
The docs have been updated with all the new features and changes of this release. To get started with new capabilities introduced in this release, go to the Concepts and the Developing applications.
Note: This release contains a few breaking changes.
Go to the upgrading Dapr section for steps to upgrade to version 1.18.
Thanks to everyone who made this release possible!
@1Ninad, @acroca, @alekhrycaiko, @antontroshin, @artur-ciocanu, @aviralgarg05, @bibryam, @CasperGN, @cerebrixos, @cicoyle, @Copilot, @cyphercodes, @Eckii24, @erj826, @erwinkramer, @famarting, @gaganhr94, @imneov, @ja-sg, @javier-aliaga, @Jeevansm25, @jjcollinge, @jmfloreszazo, @JoshVanL, @lrascao, @marcduiker, @matheusandre1, @MichaelHindley, @middt, @mikeee, @mohitpalsingh, @MukundaKatta, @MyMirelHub, @nelson-parente, @nikitasarawgi, @officialasishkumar, @olitomlinson, @pablochacin, @Pittu-Sharma, @pravinpushkar, @Rishabh-git10, @salaboy, @seherv, @sicoyle, @siri-varma, @spolom, @stywzn, @vaibhavatlan, @WhitWaldo, @yaron2, @ZeynelKoca
These are the v1.18 release highlights:
WorkflowAccessPolicy is a new Kubernetes CRD that controls which Dapr app IDs are allowed to operate on which workflows running on a target app. Before v1.18, any caller in the same trust domain could schedule, terminate, or query any other app's workflows. That was acceptable for single-team clusters but a real problem in shared or multi-tenant ones, especially now that workflows can branch into remote apps where unrestricted cross-app calls are a security risk.
The policy is a pure allow-list:
Caller identity comes from the SPIFFE identity in the mTLS certificate for remote calls, and from the local app ID for same-sidecar calls. Untrusted identity headers on user-facing requests are stripped before evaluation, so one app cannot spoof another's identity.
Rules are expressed per operation. Workflows support all eight operations — schedule, terminate, raise, pause, resume, purge, get, and rerun — while activities support schedule only. Names can be exact or glob patterns (*, ?, [abc]).
Example:
apiVersion: dapr.io/v1alpha1
kind: WorkflowAccessPolicy
metadata:
name: orders-policy
namespace: production
scopes:
# the target apps that load and enforce this policy
- orders-target
spec:
rules:
# Frontend and ops-console can schedule and terminate OrderWF.
- callers:
- appID: frontend
- appID: ops-console
workflows:
- name: OrderWF
operations: [schedule, terminate]
# Frontend can also schedule the ChargePayment activity directly.
- callers:
- appID: frontend
activities:
- name: ChargePayment
- name: "RefundEvent*"
When a call is denied, the caller receives an opaque error (access denied by workflow access policy) that doesn't reveal which rule matched or what the policy would otherwise allow.
For configuration and examples, see How-To: Apply workflow access policies and the WorkflowAccessPolicy spec. For background, see Workflow access control in the security concepts.
Workflow history events can now be optionally cryptographically signed and verified. Each step's signature is produced under the sidecar's mTLS X.509 SPIFFE identity and chained to the previous one, creating an auditable signature chain that is checked on every state load.
Each workflow execution step produces a batch of history events that are signed and chained to the previous signature:
┌─────────────────────────────────────────────────────────────┐
│ Workflow History │
│ Event 0 ─ Event 1 ─ Event 2 ─ Event 3 ─ Event 4 ─ Event 5 │
└─────┬──────────┬─────────┬──────────┬─────────┬──────────┬──┘
▼ ▼ ▼ ▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Signature 0 │ │ Signature 1 │ │ Signature 2 │
│ Events [0,2) │ │ Events [2,4) │ │ Events [4,6) │
│ prevDigest: nil ├─►│ prevDigest: d0 ├─►│ prevDigest: d1 │
└──────────────────┘ └──────────────────┘ └──────────────────┘
On every state load, the runtime verifies:
prevDigest),[start, end) ranges),If verification fails, the actor appends a terminal ExecutionCompleted event with the well-known error type DAPR_WORKFLOW_HISTORY_TAMPERED, terminates the in-flight workflow, and leaves the original (untrusted) state intact for forensic inspection.
Two additional layers extend the same integrity guarantee across app boundaries:
ChildCompletionAttestation / ActivityCompletionAttestation that commits to the parent instance ID, parent task scheduled ID, a canonical input/output digest (SHA-256 over a wire-format-independent, NFC-normalized encoding so the digest is stable across language SDKs), the signer's certificate chain digest, and the terminal status. The parent verifies the attestation on inbox ingestion and stores the foreign signer's certificate in the ext-sigcert table, keyed by certificate-chain digest.chunk.appId.Signing is a one-way decision. Once a workflow is created with signing enabled, its history must stay signed — disabling signing for that workflow (or enabling it on one that started unsigned) is a hard verification error, and there is no catch-up signing of pre-existing events. Before turning signing on cluster-wide, let any in-flight unsigned workflows complete or purge them. The feature is gated by the WorkflowHistorySigning configuration feature flag, requires mTLS to be active (daprd refuses to start with signing enabled but mTLS off), and is disabled by default in v1.18.
See Workflow history signing for how to enable signing, the verification model, and the cross-app attestation guarantees.
Workflows can now propagate slices of their history down to child workflows and activities, where the consumer can query it by name.
Two opt-in propagation modes are supported:
Propagation is per call: the caller decides whether — and what — to propagate when scheduling a child workflow or activity, and the consumer reads it back through a typed query API (for example, fetching a previously-completed activity's result by workflow name and activity name). This avoids threading state through inputs or reaching into a state store, the latter of which would break workflow determinism.
See Workflow history propagation for the Lineage and OwnHistory modes and the typed query API.
Workflow and activity concurrency can now be capped at the scheduler, across all sidecar replicas, alongside the existing per-sidecar limits. You can set a global maximum across all workflows or activities, plus per-name limits for specific workflow or activity names.
When a limit is hit, the scheduler holds triggers in a pending queue and dispatches them as slots free up via the existing ACK protocol. Global limits are sharded deterministically across scheduler instances: each replica enforces an even share of the limit, with the remainder handed to the lowest-indexed replicas so the cluster-wide total matches what you configured. Per-name limits run as independent gates, and a trigger must pass every applicable gate before it dispatches. There is one edge case: if a global limit is set lower than the number of scheduler replicas, each replica still allows one concurrent invocation to avoid starvation, so the effective cap can exceed the configured value.
spec:
workflow:
globalMaxConcurrentWorkflowInvocations: 50
globalMaxConcurrentActivityInvocations: 200
activityConcurrencyLimits:
- name: SendEmail
maxConcurrent: 5
workflowConcurrencyLimits:
- name: OrderProcess
maxConcurrent: 20
See Workflow concurrency limits for how to configure the global and per-name limits.
Previously, a workflow whose history payload (PastEvents + NewEvents + PropagatedHistory) exceeded the Dapr API gRPC server's MaxSendMsgSize (= --max-body-size, default 4 MiB) caused stream.Send on the GetWorkItems server stream to return ResourceExhausted. The whole stream was torn down, cancelling every other workflow pending on it. The SDK would reconnect, and the same offending workflow would fail again, in a loop.
In v1.18, the orchestrator precomputes the proto size of the dispatch a workflow (or activity) would produce and compares it against 95% of --max-body-size. The 5% headroom covers the WorkflowStarted event the engine injects plus gRPC framing. Anything over the threshold is gracefully stalled in a recoverable state, leaving the rest of the stream untouched. The runtime emits the payload size as a ratio of the limit so operators can watch the distribution, and a stalled instance resumes once you raise --max-body-size and restart daprd. No instance is lost.
See Workflow payload size limits for the stall behavior, the payload-size ratio metric, and how to recover a stalled instance.
A WaitForExternalEvent wait with no timeout used to be invisible to the runtime: from the outside, there was no way to tell what an instance was blocked on. In v1.18 such an indefinite wait materialises a synthetic timer (with a fire-at far enough in the future that it never actually fires), tagged with an origin that records the name of the event being awaited. With the existing RaiseEvent API, this makes approval gates and other human-in-the-loop workflows operable. The same timer-origin field also distinguishes timers created as activity and child-workflow retry delays, so every timer in a workflow's history now records why it was created.
See External events and the external system interaction pattern for how to author approval gates and other human-in-the-loop workflows using WaitForExternalEvent and RaiseEvent.
The Jobs API graduates to stable in v1.18. Performance regression tests were added as part of the stabilization work to guard against future regressions.
You should move application code to the stable ScheduleJob / GetJob / DeleteJob endpoints and the OnJobEvent callback. The alpha RPCs (ScheduleJobAlpha1 and friends) are now deprecated but remain fully functional, and the transition needs no coordination: a 1.18 sidecar still serves the alpha RPCs for older clients, and updated SDK clients fall back to the alpha RPCs automatically when they detect an older sidecar. You can upgrade the runtime and migrate application code separately.
Configuration and component hot-reloading graduates to GA and is on by default in v1.18. The following resources are hot-reloadable without restarting the sidecar:
The Subscription reconciler now skips the close+reopen when an incoming Subscription event is functionally identical to the one already loaded. This fixes a startup race where the boot-time loader and the operator stream both delivered the same subscription, which previously caused transient subscriber overlap and occasional duplicated or lost messages.
Operators who want the pre-1.18 behavior can opt out by disabling the HotReload feature in the Dapr Configuration — add it to spec.features with enabled: false.
A new MCPServer Kubernetes CRD, plus a built-in workflow orchestration engine, exposes Model Context Protocol (MCP) servers through the standard Dapr Workflow API.
When a sidecar loads one or more MCPServer resources, daprd registers built-in dapr.internal.mcp.<server>.ListTools and dapr.internal.mcp.<server>.CallTool.<toolName> workflow orchestrations. These execute MCP protocol calls as durable activities, so application code doesn't need to import an MCP SDK, manage connections, or handle credentials. The runtime handles all of that, with the same durability guarantees as any Dapr workflow.
streamable_http, sse, stdio.beforeCallTool, afterCallTool, beforeListTools, afterListTools, each able to mutate arguments / results.MCPServer resource is loaded, so sidecars with no MCP resources incur no MCP-related allocations.The preview feature gate was removed before GA; loading the CRD is now the only opt-in (#9838).
Two improvements to placement dissemination behavior at scale:
actorTable.Types() is built by ranging a map, so its order was non-deterministic. scheduler.ReloadActorTypes compares that list against the last-seen one to decide whether to reconnect, and the reordering alone made it look changed — triggering spurious reconnects on rounds where nothing actually had. It now sorts the list and skips the reconnect when the sorted set is unchanged.--disseminate-coalesce-window flag (default 0 = disabled). When set, after a dissemination round completes with queued host registers/disconnects, the disseminator arms a one-shot timer instead of starting the next round immediately. Additional host events arriving inside the window accumulate and fold into a single follow-up round. The first event in an otherwise idle state still fires a round immediately, so cold-starts and isolated churn stay responsive; only sustained bursts pay the (configurable) latency to save rounds.For 100+-replica scale-ups or rolling restarts, the coalesce window collapses what would have been O(N) follow-up rounds into O(1), removing N-1 rounds of drain+halt cost from every existing daprd in the namespace. Recommended values are 100–250 ms for clusters with frequent rapid churn. Default 0 preserves the existing behavior.
A configurable HA pod anti-affinity policy for the placement and scheduler StatefulSets in the Helm chart:
preferredDuringSchedulingIgnoredDuringExecution (default): soft anti-affinity; the Kubernetes scheduler tries to spread replicas but can still place pods when capacity is limited.requiredDuringSchedulingIgnoredDuringExecution: hard anti-affinity; enforces replica separation and may leave pods pending if constraints cannot be satisfied.Configured via global.ha.podAntiAffinityPolicy, and combinable with global.ha.topologyKey to choose the spread domain (e.g. topology.kubernetes.io/zone, kubernetes.io/hostname). The other control-plane components (operator, sentry, injector) continue to use the soft policy.
See Spreading Placement and Scheduler replicas in the production guidelines for how to configure global.ha.podAntiAffinityPolicy and global.ha.topologyKey.
Actor hosts (the application side) can now open a single bidirectional gRPC stream to daprd via SubscribeActorEventsAlpha1 and receive all four callback types — invoke, reminder, timer, and deactivate — over that one connection. Apps no longer need to expose an HTTP or gRPC server port for daprd to call into; the connection flows app → sidecar, mirroring how pubsub subscriptions, configuration watch, and scheduler job streams already work.
It also makes actor hosts deployable behind tighter firewall and NetworkPolicy rules, since there's no inbound port to allow.
Liveness probes are only appropriate as a last-resort restart mechanism for software you don't own. For processes Dapr owns, short liveness windows turn transient blips (GC pauses, startup work, brief stalls) into restart loops. Readiness is the correct lever for routing traffic away from an unhealthy replica.
v1.18 pushes liveness well past any plausible real-world stall (~230 s before kubelet restart) while making readiness more responsive:
Liveness (control plane + injected sidecar):
initialDelaySeconds: 180
periodSeconds: 10
failureThreshold: 5 (~230s before restart)
Readiness (control plane, few replicas — eject fast on failure):
initialDelaySeconds: 1
periodSeconds: 1
failureThreshold: 3 (~3s to eject)
Readiness (daprd sidecar, more forgiving for user workloads):
initialDelaySeconds: 1
periodSeconds: 1
timeoutSeconds: 1
failureThreshold: 5 (~5s to eject; absorbs brief GC / CPU stalls)
See Sidecar health for the probe defaults, and the arguments and annotations reference for the dapr.io/sidecar-liveness-probe-* and dapr.io/sidecar-readiness-probe-* annotations used to override them.
Sentry and workloads now generate X.509 certificate keys using Ed25519 instead of ECDSA P-256 for all workload identity. The migration is invisible on a fresh install or a normal upgrade.
ECDSAWithSHA256 to PureEd25519.⚠ Downgrade implications. Sentry versions before 1.17.7 cannot parse the Ed25519-keyed trust bundle that 1.18 writes to the
dapr-trust-bundlesecret and will crash on startup withunsupported key type ed25519.PrivateKey. See the new Downgrading to Earlier Versions section for the safe rollback path. Dapr 1.17.7 includes the dapr/kit PEM-decoder fix (dapr/dapr#9904) that makes 1.17.x forward-compatible with 1.18-issued bundles.
See Workload identity key algorithm in the security concepts for the full rationale, compatibility matrix, FIPS guidance, and the 1.17.7 downgrade floor. The operational view is in mTLS.
Notable component highlights this cycle:
See the full per-repo PR list below for the rest.
The marquee feature is workflow history context propagation (#823): a workflow can hand a slice of its execution history to the child workflows and activities it schedules, instead of threading that state through inputs or a state store. Propagation is opt-in per call. A producer passes workflow.WithHistoryPropagation(workflow.PropagateLineage()) (full ancestor chain) or …PropagateOwnHistory() (own events only) to ctx.CallChildWorkflow(...) / ctx.CallActivity(...), and the consumer reads back through a typed API: ctx.GetPropagatedHistory() returns a *workflow.PropagatedHistory, then GetLastWorkflowByName(...).GetLastActivityByName(...) retrieves a completed result by name. A runnable workflow-history-propagation example ships with the SDK.
The Jobs API graduates to stable (#824). ScheduleJob, GetJob, and DeleteJob call the stable RPCs and fall back to alpha against older sidecars, so one SDK build works on both 1.17 and 1.18 with no code change. The *Alpha1 client methods are deprecated and now delegate to the stable ones; the service callback is now OnJobEvent, with OnJobEventAlpha1 kept for older sidecars.
Beyond those two, this release fixes gRPC endpoint parsing when a connection string is supplied without a DNS scheme, and aligns dependencies and security baselines: durabletask-go is bumped to v0.12.1, the runtime protos to v1.18.0-rc.4, and gRPC is updated to address CVE-2026-33186.
Version mapping: Go SDK v1.15 ships with Dapr 1.18.
Since the v1.17.0 release of the Dapr runtime, the .NET SDK has continued to modularize around individual building blocks, introducing two new clients in their own NuGet packages: Dapr.SecretsManagement and Dapr.StateManagement for secret and state management operations, respectively. Beyond simply yielding smaller, more focused dependencies, splitting these clients out of DaprClient lets each package adopt more modern .NET practices and ship tooling (such as source generators, analyzers and code-fixes) tailored to its building block rather than being constrained by a single monolithic client.
This release also consolidates the Dapr.Workflow package. The separate Dapr.Workflow.Versioning and Dapr.Workflow.Analyzers packages are no longer required - both are now bundled into Dapr.Workflow itself. No refactoring is necessary, but you should remove the now-stale package references pointing to the since-deprecated packages.
Building on the automatic workflow registration introduced in v1.17, registration is now handled for both workflows and activities, meaning neither needs to be registered with dependency injection at startup as the SDK takes care of it for you. There is no need to immediately clear out your existing DI registration block when upgrading to 1.18, as the SDK will gracefully continue to accept manual and duplicate registrations, but as of this release such registration is entirely unnecessary.
Finally, this release ships several new analyzers that validate type consistency between workflow and activity inputs and outputs, surfacing mismatches at build time rather than at runtime.
This release of the Python SDK folds the durabletask-python project into the main SDK, so workflow primitives now ship in a single package with version alignment to the Dapr runtime. The MCP surface is now exposed through a dedicated workflow client, letting workflows orchestrate MCP tool calls without wiring up a separate MCP SDK.
Workflow history context propagation is available on both child workflows and activities, with opt-in scopes for the caller's own history or the full lineage; consumers retrieve the propagated history through a typed query API. Workflows and activities also accept Pydantic models as inputs, removing the previous need to hand-roll conversions.
This release also addresses several rough edges: the workflow gRPC connection now honors the standard API timeout environment variable, the default 60-second drain timeout has been removed, the maximum inbound gRPC message size is configurable via an environment variable, and workers wait indefinitely for the runtime to be ready instead of failing fast.
Bulk pub/sub is now supported, Python 3.14 is supported (with the last Python 3.9 vestiges removed), and the Jobs API graduates to stable alongside the runtime. The package layout has been simplified — unnecessary dev packages removed and version metadata centralized into a single file.
The most disruptive changes are at the build level. The minimum Java version is now 17 (#1721); Java 11 is no longer supported. The Spring Boot baseline moves from 3.4 to 3.5 (the root springboot.version goes from 3.4.13 to 3.5.12), with Spring Boot 4 supported in parallel so projects on either line are covered. The SDK also now publishes a dapr-sdk-bom artifact (#1722) you can import to keep every Dapr dependency on a single, consistent version.
On the workflow side, the headline is history context propagation (#1739), matching the other SDKs. A producer opts in per call with WorkflowTaskOptions.withHistoryPropagation(scope) (or the propagateLineage() / propagateOwnHistory() shortcuts) on child workflow and activity calls, where scope is a HistoryPropagationScope of LINEAGE or OWN_HISTORY. Consumers read back through WorkflowContext.getPropagatedHistory() and WorkflowActivityContext.getPropagatedHistory(), which return an Optional<PropagatedHistory> with typed lookups (by workflow name, app ID, or instance ID, then per-workflow drill-down to the last activity or child workflow). Workflows also gain a timer origin field (#1733) so external-event waits are visible from outside, and DurableTaskGrpcWorker now shuts down cleanly by breaking out of the gRPC worker loop instead of hanging (#1727).
For service invocation, the new DaprClient.invokeHttpClient(appId) factory (#1742) returns an SDK-native HTTP client preconfigured to call a target app, mirroring .NET's CreateInvokeHttpClient. It is the recommended successor to the now-deprecated invokeMethod APIs. Streaming subscriptions gain dead-letter topic support (#1746): subscribeToTopic now takes a deadLetterTopic to which failed messages are forwarded. There is also baggage support (#1659) and trace propagation in local observations (#1724).
On the testing side, the SDK migrated from Testcontainers 1.21.4 to 2.0.5 and from JUnit 4 to JUnit 5 (#1736).
This release is mostly about setting the groundwork to catch the SDK up to features recently introduced in other packages. Going forward, package versioning will indefinitely remain at major version 3, the minor version will track the Dapr runtime release and the patch value will reflect any mid-cycle SDK releases that don't have new runtime dependencies. Thus, as the 1.18 Dapr runtime is being release, this package releases as v3.18.0.
In the prior 3.17.0 release, CommonJS modules were inadvertently discontinued in favor of ESM as a side effect of overhauling the gRPC generators. This module-packaging change has been reverted and we have no plans to deprecate our reliance on CommonJS. Should that ever change, it will be advertised via these release notes well in advance.
The dapr-client package on NPM has been marked as deprecated for a while, but was still receiving updates, but version 3.6.1 will be the last release on that package. All updates going forward will be applied to @dapr/dapr going forward.
Workflow client methods have been renamed for nomenclature consistency with the other SDKs (e.g. "orchestrators" -> "workflows"). This is not a hard break for now. The old names remain as '@deprecated' aliases and will continue to work, with removal scheduled for the release of Dapr 1.20, so you can migrate at your own pace.
With version v0.19.0 of the Rust SDK significant changes have been made towards general stability and alignment with the other SDKs including the initialisation of the client using EnvVars and also by arguments.
As of this release, Workflows support has been added bringing almost complete support for all the Dapr APIs/Building Blocks. Siginificant changes are expected to follow after more feedback to ensure that the developer experience is improved.
This SDK is still in alpha and with each release, there are usually breaking changes. In this release the MSRV (Minimum Supported Rust Version) has been bumped to 1.88 using Edition 2024.
Please migrate to the new client implementation as documented in the examples.
allowedServiceAccounts 9793dapr-standalone-validation 9808maxMessagesCount or maxAwaitDurationMs, whichever comes first, and restarts the await-duration timer on every flush so leftover messages join the next pending batch with a fresh window. Components that declare pubsub.FeatureBulkSubscribeImmediate (Pulsar) take a flush-on-arrival path so each message is acked as soon as it arrives. 9826Dapr.SecretsManagement package #1794 to split secret management into its own clientDapr.StateManagement package #1806 to split state management into its own clientDapr.Workflow to Dapr.Common #1805 as a precursor to having common serialization across .NET SDKUnloadStateAsync implementation #1750 to force actors to unload their currently cached in-memory state (no impact to persisted state). The next time GetStateAsync is called, the cache is repopulated as normal.SubscribeAsync now throws DaprException when the sidecar is unavailable instead of failing silently #1803Dapr.Metadata package for retrieving strongly typed data from the Dapr Metadata API #1846.
To use, add Dapr.Metadata package from NuGet, register in DI with builder.Services.AddDaprMetadata() and simply inject IOptions<DaprMetadata>, IOptionsSnapshot<DaprMetadata> or IOptionsMonitor<DaprMetadata> and read the values out of the injected value.InvokeMethodAsync family marked [Obsolete] aligning SDK with prior runtime guidance — recommended guidance is to use a native HTTP/gRPC client for service invocation #1698.Dapr.Workflow meta-project (#1822) and automatic workflow/activity registration (#1823)
This means that there is no longer a need to install Dapr.Workflow.Versioning or Dapr.Workflow.Analyzers separately. All are bundled in the one Dapr.Workflow package, no refactoring necessary (though you might want to remove the stale packages).Actors.Generators #1791.Unavailable errors during integration testing via Testcontainers #1821DaprClient.invokeHttpClient(appId) factory — an SDK-native HTTP client preconfigured for service invocation, mirroring .NET's CreateInvokeHttpClient and serving as the successor to the deprecated invokeMethod APIs. 1743drain_ongoing_call_timeout to None #1016DAPR_GRPC_MAX_INBOUND_MESSAGE_SIZE_BYTES #1024aio module and update mypy configuration to include aio files #942v* tags to release #970DAPR_API_TIMEOUT_SECONDS to workflow gRPC connections #954wf purge --all-older-than --all-filter-status 5075allowedServiceAccounts 5105To upgrade to this release of Dapr, follow the steps below to ensure a smooth upgrade.
Uninstall Dapr using the CLI you currently have installed. Note that this will remove the default $HOME/.dapr directory, binaries and all containers dapr_redis, dapr_placement and dapr_zipkin. Linux users need to run sudo if docker command needs sudo:
dapr uninstall --all
Download the latest release from here and put the dapr binary in your PATH.
Once you have installed the CLI, run:
dapr init --runtime-version=1.18
Wait for the update to finish, then ensure you are using the latest version of Dapr (1.18) with:
$ dapr --version
CLI version: 1.18
Runtime version: 1.18
You can perform zero-downtime upgrades using both Helm 3 and the Dapr CLI.
Download the latest release from here and put the dapr binary in your PATH.
To upgrade Dapr, run:
dapr upgrade --runtime-version 1.18 -k
To upgrade with high availability mode:
dapr upgrade --runtime-version 1.18 --enable-ha=true -k
Wait until the operation is finished and check your status with dapr status -k.
Note: Make sure your deployments are restarted to pick the latest version of the Dapr sidecar.
To upgrade Dapr using Helm, run:
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
helm upgrade dapr dapr/dapr --version 1.18 --namespace=dapr-system --wait
Wait until the operation is finished and check your status with dapr status -k.
Note: Make sure your deployments are restarted to pick the latest version of the Dapr sidecar.
See how to deploy Dapr on a Kubernetes cluster for a complete guide to installing Dapr on Kubernetes.
You can use Helm 3 to install Dapr:
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
kubectl create namespace dapr-system
helm install dapr dapr/dapr --version 1.18 --namespace dapr-system --wait
Alternatively, you can use the latest version of CLI:
dapr init --runtime-version=1.18 -k
Verify the control plane pods are running and are healthy:
$ dapr status -k
NAME NAMESPACE HEALTHY STATUS REPLICAS VERSION AGE CREATED
dapr-sidecar-injector dapr-system True Running 1 1.18 15s 2026-05-26 13:07.39
dapr-sentry dapr-system True Running 1 1.18 15s 2026-05-26 13:07.39
dapr-operator dapr-system True Running 1 1.18 15s 2026-05-26 13:07.39
dapr-placement dapr-system True Running 1 1.18 15s 2026-05-26 13:07.39
dapr-scheduler dapr-system True Running 1 1.18 15s 2026-05-26 13:07.39
After Dapr 1.18 has been installed, perform a rolling restart for your deployments to pick up the new version of the sidecar:
kubectl rollout restart deploy/<deployment-name>
[!warning] Do not roll back from 1.18 directly to 1.17.6 or earlier.
Dapr 1.18 introduces Ed25519 workload identity keys, and Sentry persists the Ed25519-keyed CA into the dapr-trust-bundle secret. Versions of Sentry before 1.17.7 cannot parse this bundle and will crash on startup with:
fatal: error creating CA: failed to get CA bundle:
failed to verify CA bundle: unsupported key type ed25519.PrivateKey
When Sentry is down, no new workload certificates can be issued; existing sidecars with unexpired certificates keep working, but any sidecar restart or certificate expiry will fail to obtain a new identity.
| From | To | Result |
|---|---|---|
| 1.18 | 1.17.7+ | ✅ Safe. 1.17.7 backports the Ed25519 PEM-decoder fix (dapr/dapr#9904) so Sentry can read the 1.18 trust bundle as-is. |
| 1.18 | 1.17.6 or earlier | ❌ Sentry crash-loops at startup. Do not attempt this rollback. |
| 1.17.6 or earlier | 1.18 | ✅ Safe. 1.18 Sentry accepts CSRs of any algorithm; existing ECDSA P-256 bundles are read transparently. |
If you must downgrade below 1.17.7, go through 1.17.7 first:
dapr status -k is healthy.Use Helm rollback (preferred) or re-install at the target version:
# Helm: list revisions, then roll back to the desired one
helm history dapr -n dapr-system
helm rollback dapr <REVISION> -n dapr-system --wait
# Or pin a specific version
helm upgrade dapr dapr/dapr --version 1.17.7 --namespace dapr-system --wait
After the control plane is back, perform a rolling restart of your application Deployments so sidecars pick up the older injector image and re-issue their identities against the rolled-back Sentry.
Going 1.18 → 1.17.7 does not require manual CA rotation. The Ed25519-keyed bundle remains valid; 1.17.7 reads it, continues to issue new CSRs against the existing trust anchor, and ECDSA/RSA CSRs from 1.17.x sidecars are signed normally. Only re-rotate the CA if your downgrade target is below 1.17.7 or if your security posture requires it.
[!warning] Review carefully before upgrading
WorkflowsRemoteActivityReminder default-on. Cross-app workflow activity results are now delivered via Scheduler reminders by default. See dapr/docs#5128 and dapr/dapr#9789.HotReload feature in the Dapr Configuration (spec.features with enabled: false). See dapr/dapr#9811.an active workflow with ID '<id>' already exists) instead of silently overwriting or ignoring it. Callers that previously relied on the silent-overwrite or ignore behavior must adapt. See dapr/docs#5102.Connection, Keep-Alive, Proxy-Authenticate, Transfer-Encoding, etc.) are now stripped during service invocation, per RFC 7230. Apps relying on these passing through must move to non-hop-by-hop equivalents. See dapr/docs#5172 and dapr/dapr#9759.dapr-client removed. The standalone dapr-client npm package is no longer published. Consumers must move to the unified @dapr/dapr package. See dapr/js-sdk#773.invokeMethod APIs (deprecated). Use the new DaprClient.invokeHttpClient(appId) factory introduced in this release. See dapr/java-sdk#1743.InvokeMethodAsync family marked [Obsolete]. Recommended guidance is to use a native HTTP or gRPC client for service invocation. See dapr/dotnet-sdk#1698.get / start / raise are renamed to getWorkflowState / scheduleNewWorkflow / raiseEvent for consistency with the other SDKs. The old names remain as deprecated aliases and continue to work, with removal scheduled for Dapr 1.20. See dapr/js-sdk#783.