
Every distributed application gathers various plumbing components. One service requires retries and timeouts, another needs a message broker client, and a third must store some state, retrieve secrets, or discover other services. Over time, each team ends up with a unique set of client libraries, connection handling methods, telemetry, and failure behaviors.
Dapr, the Distributed Application Runtime, provides a uniform API for the underlying infrastructure. Your application communicates with a local Dapr process via HTTP or gRPC. Dapr then interacts with services, the state store, the broker, the secret store, or other components on your application’s behalf. While the application retains control of its business logic, Dapr offers reusable capabilities for building distributed applications.
This separation explains why Dapr is valuable on Kubernetes and AKS. While Kubernetes handles container scheduling and management, it lacks a standard API for application-level functions such as state, messaging, workflows, or secrets. Dapr addresses this gap, enabling services to interact seamlessly without needing to use the same language or SDK.
The short version: use Dapr when you want common distributed-systems behavior behind portable application APIs. Don’t use it just because an application runs on Kubernetes.
This is the first post in the Dapr on Kubernetes and AKS series. It establishes the mental model; the next posts turn it into a working local environment and then an AKS deployment.
The problem is repeated integration, not missing code
Consider an order service built in .NET, a stock service implemented in Go, and a notification worker created in Python. These components must communicate, publish events, save data, retrieve credentials, and generate useful traces. Without a common runtime, each team selects and configures its own libraries for these tasks.
The first implementation usually works. The cost appears later:
- retry policies differ between services and sometimes amplify an outage;
- broker-specific code leaks into business logic;
- tracing stops at asynchronous boundaries;
- secrets are loaded and refreshed in several different ways;
- replacing a state store or message broker becomes an application rewrite; and
- platform standards have to be implemented once per language stack.
Dapr does not make a distributed system simple. Network calls can still fail, messages can still arrive more than once, and data still needs a deliberate consistency model. Dapr can make the plumbing consistent and move much of the integration-specific code behind stable APIs.
An application can publish via Dapr’s pub/sub API without importing a specific broker’s SDK. A platform team can configure the pub/sub component independently. Although switching components doesn’t guarantee a completely effortless migration since brokers vary in semantics and capabilities, it minimizes how much a technology choice affects application code.
The sidecar is the boundary
Dapr typically runs a daprd process alongside each enabled application instance. In Kubernetes, this process is executed as a separate container within the application pod. Since both containers share the same pod network, the application communicates with Dapr through a local HTTP or gRPC endpoint.
The request path is deliberately local at the start:
- The application calls a Dapr API on localhost.
- The sidecar applies the relevant building-block behavior and configuration.
- The sidecar talks to another Dapr-enabled service or to a configured component.
- Telemetry, resiliency, security, and component behavior are applied at that boundary where supported.
This gives polyglot teams a useful contract. A Java service and a Python worker can use the same HTTP or gRPC APIs even when their language ecosystems differ. Dapr SDKs can make those APIs more convenient, but they are optional rather than the architectural boundary.
The trade-off is genuine: each enabled application replica requires additional resources for scheduling, monitoring, upgrading, and processing. Calls also incur an extra step through the local sidecar. Whether the benefits of consistency and portability justify this cost depends on the workload. A small monolith communicating directly with a single database may see little advantage. In contrast, a polyglot system with recurring state management, messaging, service invocation, and workflow requirements is a much stronger candidate for Dapr.
Dapr is not a service mesh
The shared use of sidecars creates the most common Dapr misunderstanding. Dapr and a service mesh can both provide mTLS, retries, metrics, and tracing, but they operate from different starting points.
| Dapr | Service mesh |
|---|---|
| Exposes application APIs that developers call deliberately | Primarily manages network traffic between workloads |
| Adds building blocks such as state, pub/sub, actors, secrets, and workflows | Adds traffic policy, routing, encryption, and network-level observability |
| Uses an application identity such as a Dapr app ID for service invocation | Commonly reasons about services, workloads, addresses, and network routes |
| Changes application integration code to call Dapr APIs | Can often be introduced without changing application code |
The two complement each other when a platform needs both application building blocks and advanced network traffic management. They also overlap. If you deploy Dapr and a mesh together, decide explicitly which layer owns mTLS, retries, and tracing; duplicating those behaviors can produce confusing telemetry and unsafe retry multiplication.
Dapr should therefore not be sold as a lighter Istio or Linkerd. A mesh is infrastructure-centric. Dapr is developer-centric. The choice is not automatically one or the other.
The building blocks at a glance

Dapr is incrementally adoptable. An application can use one building block without committing to all of them.
- Service invocation calls another application by its Dapr app ID through HTTP or gRPC. Dapr can add discovery, security, tracing, and configured resiliency to the call path.
- State management stores and retrieves key-value state through a common API. Capabilities such as transactions, queries, concurrency, and consistency depend on the selected state component.
- Publish and subscribe separates publishers from subscribers through topics and a configured message broker. Dapr carries events using CloudEvents by default and supports routing and delivery controls.
- Bindings connect an application to external systems through input triggers and output operations. They are useful when the integration fits a component’s contract and does not justify custom client code.
- Actors implement virtual, addressable entities with encapsulated state and turn-based concurrency. They fit some stateful domain models well and are unnecessary for ordinary stateless services.
- Secrets retrieve secret values through a consistent API or let other Dapr components reference them, keeping secret material out of component definitions.
- Workflow coordinates durable, multi-step processes whose execution must survive restarts and failures.
- Configuration lets applications subscribe to changes in supported configuration stores without embedding a store-specific client.
These APIs are backed by components. A state API might use Redis in development and Azure Cosmos DB in another environment. Pub/sub might use Redis Streams, Apache Kafka, or Azure Service Bus. The API is the application contract; the component is the adapter and its configuration.
Portability still has edges. Not every component implements every optional feature, and operational characteristics don’t become identical just because the API is shared. Treat component capability tables and backing-service behavior as part of your design.
Why Kubernetes is a natural host
Kubernetes gives Dapr a consistent way to attach the runtime to applications. When a workload is annotated for Dapr, the sidecar injector modifies newly created pods and adds the daprd container. This keeps the application image independent from the runtime and makes the pattern repeatable across deployments.
A Kubernetes-mode Dapr installation also adds control-plane services, normally in the dapr-system namespace:
- the sidecar injector adds Dapr to annotated pods;
- the operator watches Dapr resources and communicates component updates;
- Sentry issues and rotates workload certificates used for Dapr mTLS;
- Placement maintains actor placement information; and
- the Scheduler supports scheduling and durable execution capabilities used by jobs, actors, and workflows in current Dapr releases.
Kubernetes custom resources provide platform teams with a declarative way to manage Dapr components, configurations, subscriptions, resiliency policies, and related resources. Kubernetes also offers the necessary operational infrastructure, including namespaces, service accounts, deployments, health checks, resource controls, and rolling updates.
None of this implies that Kubernetes is necessary. Dapr also enables self-hosted development and supports various hosting options. Kubernetes is especially suitable when you already need a cluster, offering consistent injection, declarative setup, and lifecycle control.
What AKS adds
AKS does not alter Dapr’s application APIs; instead, it modifies the surrounding platform. Initially, AKS offers a managed Kubernetes control plane along with Azure integrations for identity, networking, policy, monitoring, and container registries. Dapr components can then interface with Azure services like Azure Service Bus, Azure Cosmos DB, Azure Cache for Redis, and Azure Key Vault. When a component supports Microsoft Entra authentication, AKS Workload Identity eliminates the requirement for long-lived connection strings.
Second, Microsoft offers the Dapr extension for AKS. This extension deploys the Dapr control plane via Azure’s cluster-extension system and manages versioning and configuration. Microsoft advises keeping clusters installed with this extension managed through it, rather than mixing extension management with Dapr CLI operations.
The extension reduces installation effort but does not make the Dapr runtime an Azure-managed service. You remain responsible for application annotations, component design, identity and access management, sidecar resources, observability, upgrade policies, and backing-service behavior. Additionally, understanding the difference between Microsoft support for extension operations and upstream Dapr runtime issues is important for setting correct production expectations.
Installing open-source Dapr into a small Kubernetes cluster is quick and straightforward for local learning. When using an AKS platform, the extension becomes the clear choice since it aligns with Azure’s lifecycle management and offers high availability out of the box. We will explicitly compare both approaches later in this series.
When Dapr is a good fit
Dapr deserves a proof of concept when several of these are true:
- services are written in multiple languages;
- the same integration concerns recur across teams;
- applications need service invocation, messaging, state, secrets, or durable workflows;
- the platform team wants a shared contract without prescribing one language framework;
- portability between supported component implementations has real value; or
- developers need consistent local and Kubernetes-hosted behavior.
Pause before adding it when the architecture is simple, direct client libraries are effective, latency is highly critical, the organization can’t support another runtime, or only a limited feature set will be used. A platform abstraction is valuable when it reduces more complexity than it adds.
The most effective adoption approach is incremental. Start with a single bounded problem such as service invocation between two services or publishing a single domain event and evaluate its impact on code quality, latency, operability, and failure behavior. Avoid migrating everything at once just to test a hypothesis.
What comes next
Continue with Installing Dapr on Kubernetes Locally with OrbStack, where we build a local cluster, inspect the current control plane, and deploy a minimal Dapr-enabled service. After that, we will move the same mental model and sample workload to AKS.
Continue with the Dapr on Kubernetes and AKS series index.
Sources
- Dapr Docs — Dapr concepts
- Dapr Docs — Dapr sidecar overview
- Dapr Docs — Dapr and service meshes
- Dapr Docs — Dapr building blocks
- Dapr Docs — Dapr on Kubernetes
- Microsoft Learn — Dapr extension for AKS and Arc-enabled Kubernetes
- Microsoft Learn — Install the Dapr extension for AKS