Dapr in Action: Creating Reliable Applications
Discover the nature of Dapr (distributed application runtime). Learn how you can leverage it in cloud app development, its pros and cons.

Developing cloud-native applications and managing interactions between their components is a highly complex task. Integrating everything seamlessly can be quite challenging.
The quality of these solutions relies heavily on the team's expertise and experience. You must write precise code that accounts for countless details, such as fault tolerance, observability, and scalability. Additionally, most frameworks focus primarily on individual services rather than the entire system, and their effectiveness often depends on the chosen programming languages.
It has become evident that we need a framework that addresses the bigger picture.
The rapid advancements in cloud-native tools and Kubernetes have enabled the creation of such a framework. This led to the development of the Distributed Application Runtime (Dapr).
Understanding Dapr
Dapr was originally created by Microsoft employee Yaron Schneider and serves as a set of building blocks that can be integrated into applications. These building blocks hide the complexities of implementation, offering standardized interfaces for common tasks in distributed systems. Moreover, Dapr addresses key cross-cutting concerns such as observability, service discovery, resilience, and security. Its benefits are most pronounced in microservice architectures, where these concerns must be handled individually across multiple services. Keep in mind that these services may be written in different programming languages, adding an extra layer of complexity even before you begin writing business logic.

Dapr is architected as a sidecar that runs alongside your application, delivering its services through an API, as illustrated in Figure 2. This design makes perfect sense.
You may have come across the concept of Service Meshes, which is somewhat similar but not identical to Dapr. While Service Meshes primarily simplify service discovery and communication, Dapr offers a broader range of capabilities. Similar to service meshes (such as Istio), each service in your application gets its own Dapr sidecar injected into the Kubernetes pod. This sidecar functions as a gateway to a suite of powerful building blocks provided by the framework. Of course, you remain free to use external resources as needed, such as connecting to a PostgreSQL database or interacting with a Redis cache. You only leverage the tools you require, which is one of Dapr's key strengths. This flexibility allows you to gradually modernize existing applications at your own speed. Simply add the sidecar, and you take a step closer to achieving optimal engineering efficiency.

At its core, Microsoft Dapr is designed to be language-agnostic, even though SDKs are available for specific languages. You can interact with the sidecar using either the well-documented HTTP API or opt for gRPC if you need higher performance. Internally, Dapr sidecars communicate with each other exclusively through mTLS-secured gRPC connections, forming a network of sidecars linked to their corresponding applications. When an application needs to interact with another, it sends a request to its local Dapr sidecar, specifying the recipient's name, the method to invoke, and any data required. Simplifying communication is just one of the many capabilities that Dapr makes effortless and transparent.
The true power lies in the building blocks, which offer additional functionality beyond just communication.
Creating blocks with Dapr
The capabilities of the framework extend far beyond service discovery and request bridging. Each Dapr sidecar serves as a gateway to a suite of APIs that address common needs in distributed applications, such as dynamic configuration, secrets management, cryptographic operations, publish-subscribe messaging, scheduled jobs, bi-directional bindings for external services, distributed locking, actor models, and workflow orchestration.
Essentially, it's like having a comprehensive library of these functionalities right next to your service, accessible via HTTP or gRPC. If you're concerned about the performance impact of network access, consider this: since these services are inherently distributed, there would be some overhead regardless of whether they're implemented inside or outside your service. On the upside, you save time by not having to build these features from scratch or integrate language-specific libraries. Instead, you benefit from a collaborative effort that continually improves a single, unified piece of software. Regardless of the programming language you use for your service, the building blocks remain consistent, eliminating the need to reimplement or synchronize across different technologies.
Many of these building blocks rely on external servers, tools, or cloud services to function. For instance, state management requires a storage backend (like PostgreSQL or Redis), while the publish-subscribe block depends on a message broker (such as RabbitMQ or Kafka). These are not bundled with Dapr in Kubernetes; instead, Dapr provides implementations for various building blocks that need to know where the actual database or broker is deployed. This configuration is declarative and can typically be managed by DevOps during deployment. Thanks to active community contributions, there are already hundreds of building block implementations, with more being added regularly.

Deployment
Dapr is designed with Kubernetes in mind, making it straightforward to set up your cluster for a distributed application runtime. After installation, a dedicated namespace is created, hosting several Dapr system containers. These containers serve as a registry, job scheduler, certification center (for managing mTLS certificate rotations), and an open telemetry trace collector like Zipkin. That’s all there is to the setup.
When you decide a service requires Dapr, simply add a few labeled lines to the Deployment manifest file. This triggers the Dapr injector controller to automatically inject a sidecar container into the Pod alongside your service.
Microsoft's Dapr tooling includes a development mode that allows you to run your service locally in the terminal, simulating the presence of the Dapr sidecar. It launches your service and monitors its health. Once the application initializes, it registers itself with a local registration service running in Docker. This enables other applications started in the same manner to discover and interact with each other by name, providing a complete simulation of a real deployment. In many cases, this setup is sufficient for developing application services efficiently.
One of the standout features is that the manifests written for local development are identical to those used for actual deployment to the Kubernetes cluster. While it’s important to handle secrets securely and avoid using "localhost" for dependencies, the manifests can otherwise be used directly, offering a convenient advantage.

Distributed application runtime: Disadvantages
Here are some potential downsides or reasons why Dapr might not be the right fit for you:
- Kubernetes Focus: Dapr is primarily designed for Kubernetes. If you're not using Kubernetes, it might feel cumbersome. You'd need to manually pair each application container with a Dapr sidecar, ensuring they only run together when healthy. This can add unnecessary complexity if Kubernetes isn't part of your stack.
- Monolithic Applications: If your application is monolithic and you don't plan to break it into smaller services, Dapr might not offer much value. While you could still use features like configuration, secrets, or external service bindings, maintaining the sidecar outside Kubernetes might not be worth the effort.
- Radical Approach: Dapr introduces innovative but sometimes radical concepts (e.g., strict state management rules). Adopting it might require a significant shift in how you design applications. Some teams might resist these changes, so consider whether your team is ready to adapt. Introducing Dapr gradually, starting with complex cross-service interactions, could help ease the transition.
- Immature Framework: Despite graduating from CNCF incubation in late 2024, Dapr is still relatively new. While it evolves quickly and has strong community support, bugs and inconsistencies remain. For instance, we encountered issues with query pagination in PostgreSQL and MongoDB, making them less interchangeable. If your team isn't confident in handling such challenges, you might want to wait for the framework to mature further.
In summary, while Dapr offers powerful tools, it may not suit every project or team due to its Kubernetes focus, complexity for monolithic apps, radical design shifts, and relative immaturity.
Conclusion
Last year, we made the fantastic discovery of Dapr, and we can clearly see how it is changing the field of developing cloud-native distributed systems. Although it's still in its infancy and we periodically discover issues, it appears to be a strong basis for the creation of distributed applications. Additionally, it does not confine you to a certain language or technology.
It is being used in both our pet and pilot operations. started out slowly, as we previously recommended, and is currently adding more and more features. We hope that this little essay piqued your curiosity in Dapr microservices and encouraged you to do more exploration. There will be other articles about this subject!
Written by Mary Moore and Aleksey Gureiev
About the Creator
Shakuro
We are a web and mobile design and development agency. Making websites and apps, creating brand identities, and launching startups.



Comments
There are no comments for this story
Be the first to respond and start the conversation.