Dapr as a 10x Platform
In this post, we'll explore why Dapr is a 10x runtime that emerged at the right time and what its drawbacks are.
For a new idea to spread, for a project to be widely adopted and become mainstream, it must be at least 10x better than the status quo to justify the effort for the change. Microservices architecture has improved release cycles for most organizations from quarterly (12 weeks) or longer to weekly and even shorter. Docker made it possible to run dozens of services without resource conflicts on one host instead of ten. Kubernetes enabled operations staff to operate 10x more services. These are all examples of 10x improvements. But implementing new ideas and adopting new technologies also come with costs and new drawbacks. Identifying domain boundaries, implementing network resilience, debugging, testing, and running microservices is the cost that didn't exist in monolithic architectures. Learning Kubernetes, getting used to asynchronous reconciliation behavior, and debugging issues requires brand new skills and tools. Yet the magnitude of the holistic value of these new architectures and tools to organizations justifies the pain of change. In this post, we'll explore why Dapr is a 10x runtime that emerged at the right time, what benefits it provides for the different roles in an organization, and what its drawbacks are.
Dapr offers a different approach than the traditional library-based approach to using integration features. It's a toolkit that provides APIs for distributed systems via a sidecar, making it a good solution for cloud-native applications, both new greenfield and when migrating existing brownfield applications. While Dapr is primarily used by developers building applications, it also improves the lives of operations staff running those applications and architects trying to bring order to an organization's applications and tools inventory. Let's start by looking at what benefits Dapr brings to the various roles in the enterprise, and then at what it costs to adopt it.
Benefits for developers
Developers have a wide range of responsibilities from understanding the business domain, creating new applications, maintaining old ones, and even innovating in areas the business hasn't thought of. For the purpose of this article, we focus on developers creating new distributed applications and delivering them to a fast business schedule. From that angle, what are the areas that Dapr can help developers in a noticeable way?
Microservices is the dominant architecture for new applications and synchronous inter-service communications are at its core. Dapr service invocation API helps developers handle problems like service discovery, secure inter-service communication, request timeouts, retries, load balancing, etc.
Publish and subscribe
Another architectural trend with microservices is to use event-driven interactions with some kind of publish-subscribe implementation. Dapr provides a platform-agnostic API to send and receive messages which integrates with various message brokers and queuing systems through a pluggable component mechanism. This enables portability across local and production environments, and deployment of the same application on different cloud providers offering different pub-sub and other services.
3rd party integration
Another necessity of modern cloud native applications is integration with 3rd party services and well-known APIs. Using Dapr's bindings API, you can trigger your app with events coming in from tens of external systems and interface with external systems by keeping your code free from SDKs or libraries. This prevents developer form having to deeply understand how to use a particular SDK for connecting to external systems or recovering from endpoint-specific failures. The net result is that developers can focus on the business logic and create portable applications without environment or cloud provider-specific bindings within the applications.
Reproducing a production-live environment for local and shared-test environments is an ever-lasting challenge. Among other things, it requires configuring an application, discovering other locally running services, accessing external dependencies such as databases, message brokers, local representation of cloud services, etc. In large organizations with many developers, it can get costly to create dedicated environments, and some of these dependencies have to be shared. Dapr's configuration API allows developers to consume configurations and subscribe to changes whenever a configuration item changes. Dapr's service invocation API allows the discovery of services deployed locally or in the production environment. Dapr's pub/sub and state APIs allow swapping message brokers and state stores without any changes to the application code. With that, developers can develop against a local Redis broker for example, and replace it with a cloud service in production through configuration only. Dapr also simplifies sharing message brokers and state stores among multiple developers. Dapr can act as the foundational developer platform that allows the creation of portable and polyglot applications by multiple teams.
There is more
There are other features in Dapr that boost developers' productivity, but it is beyond the goals of this post to go into them. Dapr's state management API can do CRUD operations with abstracted state stores. Dapr actors can implement large numbers of small, independent, and isolated units of state and logic. Other primitives such as distributed locks can provide mutually exclusive access to a resource. New features built on top of existing ones such as orchestrating long-running processes are coming up too. All of that makes Dapr a powerful distributed toolkit in a box that is hard to ignore by cloud-native developers.
Benefits for operations
This is another broad category of IT personnel, and for the purposes of this post, it includes traditional operations teams, site reliability engineers, and even the newer platform engineering teams. All teams are not writing applications, but keeping the applications running and enabling developers to do their job more effectively. While Dapr is primarily a developer toolkit, once introduced into applications, it improves the life of operations teams too. Let's see how Dapr helps with automating and operating large numbers of applications at scale.
Security is a responsibility of many teams, but here we will summarize the areas in which Dapr helps operations-like teams around application security.
- Dapr has a dedicated secrets building block that allows developers to get secrets from a secret store such as Azure Key Vault, Hashicorp Vault and others. The cool thing is that these secrets can be scoped for specific applications and also can be used by other Dapr components such as state stores, pub/sub components.
- When looked at from a networking point of view, Dapr has features that overlap with those of a service mesh Dapr is like a service mesh. Dapr helps with in-transit encryption of communication between service instances through mTLS. Dapr allows operators and developers to bring in their own certificates, or instead let Dapr automatically create and persist self-signed root and issuer certificates.
- While mTLS can encrypt the traffic between sidecars, Dapr supports API token authentication for an additional level of security between the app and the sidecar. Enabling token-based authentication causes Dapr and/or the application to require every incoming request for its APIs to include an authentication token, before allowing that request to pass through. This approach offers a truly end-to-end service invocation security by extending proxy-to-proxy authentication into app-to-app.
- Dapr OAuth 2.0 feature allows you to enable OAuth authorization on endpoints so that any method invocation through Dapr needs to be authorized before getting passed to the user code. This does not require any additional code to be written except for the middleware configuration.
- Access controls in Dapr offer configuration policies that restrict what operations calling applications can perform, via service invocation, on the called application. To limit access to a called application from specific operations and HTTP verbs from the calling applications (through a SPIFFE id), you can define an access control policy specification in configuration.
- In zero trust networks or when exposing Dapr to external traffic through a frontend, Dapr APIs can be scoped to the actual needs of the application and reduce the attack surface.
- By its very nature, the Dapr sidecar creates a boundary between the business logic and infrastructure code running processes. The segregation of application code from infrastructure code helps identify the scope of a breach and can help remediate faster by pushing new versions of the code that touches only the affected parts.
As listed above, Dapr security benefits are multi-faceted, some are explicit features to use, and some are indirect benefits thanks to its sidecar architecture. The non-intrusive nature of Dapr means you can use only the features you want and combine Dapr with other similar tools such as service meshes.
Dapr provides implementations for popular resiliency patterns, such as Timeouts, Retries/back-offs, Circuit breakers. What's cool about Dapr is that these patterns can be applied not only to applications that perform service invocations but also to Dapr components. That means, in addition to the built-in resiliency features, components that interact with other systems can benefit from additional fault tolerance through resiliency patterns.
Since Dapr is on the request path to service interactions and acts as the glue to other systems, it has access to a rich set of application metrics, tracing and logging data that most other frameworks don't. The main source of observability data in Dapr comes from the following.
- Dapr exposes a Prometheus metrics endpoint that you can scrape to gain a greater understanding of how Dapr is behaving and set up alerts for specific conditions.
- Dapr intercepts all application traffic and automatically injects correlation IDs to trace distributed transactions. Since Dapr is not limited to only service-to-service interactions, it can also trace and monitor interactions with external systems over various protocols and APIs. It uses the Zipkin protocol combined with the OpenTelemetry collector for distributed traces and metrics collection and supports many backends out of the box, for example, Stackdriver, Zipkin, New Relic, and others.
- Both the Dapr data plane (sidecar) and control plane (system components) produce logs. In addition, it is possible to enable API logs, which will log all API calls to and from Dapr sidecar which can be very handy to understand an application's networking behavior.
The term Golden Path was introduced in IT by the platform engineering team at Spotify. It represents an opinionated and internally supported path to building software through "blessed" tools and processes. And the idea is not to limit or hinder the developers, but to allow them to use their productivity and creativity for higher objectives by making fewer decisions and not reinventing the wheel during day-to-day activities. In practical terms, that means offering developers proven, supported i.e. golden paths for creating software and other common tasks. Let's see what aspects of Dapr make it attractive as a foundation for a developer platform with golden paths.
- Dapr is a multi-environment framework. It is light to run locally, with multi-tenancy features to run a shared environment, or in production. It can run on-premises, cloud, or at the edge. In addition to running in different environments, Dapr bindings allows it to connecto to various services that run and vary among the different environments without any application code changes.
- Dapr is non-intrusive. It is not included in an application as a library, and it doesn't intercept all the application traffic like a service mesh. Therefore, it is up to you to pick which building blocks to use, and up to your application when to interact with Dapr APIs. That makes Dapr capabilities optional to use only when it is justified to use.
- Separation of concerns for Dapr configurations. Dapr capabilities are explosed to application developers as building block APIs. But these building blocks rely on components that provide the implementation. Typically these components would be configured by operations teams with higher permissions on the platform and the cloud infrastructure and offered to developers as ready-to-use. This separation allows operations to guide and even control which infra pieces developers could use and which not.
All of these characteristics make Dapr very attractive across the organizations as a foundational platform within an organization. Typically these capabilities are offered as the Golden Path and centrally automated and managed by platform engineering teams. Dapr is generic enough to suit most teams, non-intrusive to be used only when needed, and easy to manage and configure centrally from platform teams.
Benefits for architects
Among other things, the role of the architect is to be the interface between the technology and the business and use that combined knowledge to align the development and operations teams towards the business goals. To optimize technology, people and processes across multiple teams and timeframes that individual developers might not be aware of. With that definition of the architect role, let's see what are some of the architectural concerns that Dapr can help with.
If you are a developer in a team, you have probably mastered a programming language, you know its ecosystem of libraries and tools well, and are not impacted by what other teams in the organization are using day to day. If you are an enterprise architect dealing with multiple teams, working on multiple projects, and have a time horizon longer than a project's length, it is a different story. To design a solution, you have to know what language the team is using, what frameworks are available, what capabilities they offer, their licenses, lifecycle, support, and whatnot. On the other hand, Dapr is designed to be polyglot and it doesn't make assumptions about what language it is used with. That makes all Dapr building blocks, components, and patterns, available to everybody under the same terms. While this might not be an important characteristic for a single developer or team in the short term, it is immensely important when looked at an organization level and longer timeframes.
Today, multi-cloud is not the shiny end goal but the ugly reality many architects have to deal with. Many organizations run on-premise software and also on one or more cloud providers. That sometimes is on-purpose to benefit from certain business arrangements, specific cloud features, or by accident due to acquisitions or shadow IT. Whatever the reason, being able to run an application in different environments, or even having the optionality to migrate can be desirable. Sometimes that optionality is needed in early stages when a solution is designed and before the final environment is procured and confirmed, and sometimes later as a backup option. An architect designing a solution will have different timeframes and different assumptions in mind, than a developer who already has the environment available during the implementation. Dapr is designed to run best on Kubernetes, but it also runs on VMs, the cloud, or the edge. It has bindings that can connect to different cloud services wherever your application is running at. All that makes Dapr a portable implementation of common patterns and connectors giving architects a common ground for designing solutions that are portable across environments and implementation optionality.
One of the less-spoken portability aspects of technology is knowledge and human portability. For example, one would use Java for a new project not because its bytecode is portable on multiple operating systems, but because its JVM is reliable and there are millions of developers that can be hired when the core developers move on. One would use Hibernate (it is an ORM framework) not to swap the database with another one, but because it has a proven-in-the-years implementation, it has well-known patterns and programming model, and you can get a developer that knows how it works. One would use Kubernetes not because Kubernetes can be ported to a different cloud provider, but because all the operational knowledge and practices can be ported from a cloud provider and applied to another and on-premise by the same operations team. Reusing code is effective, only when combined with reusing knowledge. It is the same idea as Dapr. Dapr provides an implementation of common connectors, patterns, and distributed systems primitives that can be ported to different teams and environments. It is the most non-intrusive, portable distributed systems toolkit created to date. Once learned, the same development, operations, and architectural knowledge can be ported and applied in all parts of the organization for all kinds of projects.
Maintenance is the process of changing, and updating software to keep up with new requirements, fixing bugs, optimizing performance, etc. It is an aspect of the software lifecycle that is spread over time which makes it less important to consider at the early stages of a new project, but it can turn out to become the most expensive phase in the long term. Having a platform that eases maintainability is a plus that architects with a long-term view appreciate. Which are the aspects of Dapr that help with software maintenance?
- Fewer dependencies: Regardless of the language used, Dapr provides connectors to a wide range of external systems which leads to less 3rd party library dependencies in your projects. That means fewer libraries cashed in local repositories, in artifact repositories, and container registries. That means fewer libraries to track across projects for updates, security fixes, and licensing implications. That means less external influence on your project timelines and budget.
- An API-based dependency: Dapr is also an external dependency, but it runs as a separate process and it is accessed over well-defined APIs with versioning policy. As a consequence, you can apply a Dapr security fix by updating Dapr versions and restarting your application Pod. That means the development team doesn't have to do changes to the application dependencies, test it, build it, create containers, etc (unless of course the Dapr client library is used and the bug is in the client library, and you are updating the client library). That means the development teams don't have to stop working on a feature to apply an emergency fix, or a regular upgrade to the latest versions of external dependencies. Dapr upgrades can be carried out by platform engineering teams and offered to developers as a common foundation that they can consume over a stable API (like a cloud service).
- Declarative and configuration driven: Dapr capabilities are exposed over HTTP and gRPC APIs, but Dapr is configured with Kubernetes-like declarative API. In fact, the Dapr configuration file is a Kubernetes CRD, regardless of whether you are using Dapr in Kubernetes or not. Declarative APIs are easier to understand and maintain and allow you to configure and tune Dapr through the same automation tools and practices used for other cloud native projects.
- Separation of concerns: Using Dapr results in the creation of loosely coupled application components that can be easily exchangeable and connected to their software environment. Notice that this is also the definition of Hexagonal architecture which Dapr is a natural fit for. When using Dapr, the technical integration responsibilities get concentrated in Dapr, and the business logic is encapsulated in the application layer. This provides the same benefits of Hexagonal architecture such as delaying and changing technology decisions, testing and changing business logic in isolation of external systems.
Part of an ecosystem
Dapr came into existence at a time when microservices are the dominant greenfield application architecture, open source is the dominant development model, and open standards is the dominant innovation and adoption model. As a consequence, we saw one of the fastest adoptions of new technologies such as Docker and Kubernetes. We see an increasing growth of complementary technologies such as Prometheus, Zipkin, Jaeger, Fluentd, and the resulting open standards such as OpenTelemetry, W3C Trace Context, Kubernetes API, CloudEvents, and so on. As a CNCF incubating project, Dapr is built on the same cloud-native principles that Kubernetes is built on, and it benefits and complements other cloud-native projects contributing to the compounding business value for end users. While sidecars have existed long before Kubernetes, now the industry has grown to better understand this architecture, and it is better equipped to consume and operate this programming model.
Negative engineering is a term used to describe work that has to be done to do the main work. For example, you need to deal with the network fallacies to adopt microservices. You need to learn distributed systems and write in YAML to work with Kubernetes.... If all of the above are examples of why Dapr is a 10x framework and how it helps various roles positively, then what are the drawbacks of using Dapr? Here are a few that are most commonly pointed at downsides of Dapr.
Among the biggest challenges of adoption Dapr is the perceived increased complexity of having multiple moving parts. The reason I say it is perceived is that if you are doing Microservices, you are already dealing with distributed systems and operating multiple processes. Interacting with Darp is not different, other than the fact that Dapr happens to run local to each of your services. Dapr doesn't transparently modify any application networking rules, nor does it intercept all network traffic to your service as is the case with service meshes. Dapr is a technical component that exposes an API for your service to interact with, and it interacts with your application over well-defined APIs. While it is a new paradigm that takes courage to start with, and practice to get used to, today's development and operational tools help significantly with running sidecars and operating them.
If low latency is a critical requirement for an application, then microservices running on Kubernetes, on top of commodity cloud infrastructure might not be the right architecture to start with. You might be better off with a monolithic application running on specialized hardware or mainframe for best performance. Let's assume that is not the case, but you still want to have a low-latency distributed application running on Kubernetes. Increased network latency due to an extra network hop is a common side-effect of proxy-based technologies such as Dapr. It is a well-known fact that Dapr will add around 1ms to 2ms latency to 90 to 99 percentile of requests which is lower than other similar sidecar-based service meshes. What's more, since Dapr is not intercepting all traffic in and out of the application scope, you have control over when to use Dapr and add the extra latency. The chances are, that not all microservices in an application will be sensitive to latency. Even further, not all service endpoints will be sensitive to the slight increase in latency. You can use Dapr at the edges of your application to integrate with other systems where extra latency is unavoidable. You can use Dapr for most service and data source interactions, and use native drivers, binary protocols, etc to interact with systems that are latency sensitive. Dapr is a non-intrusive, opt-in toolbox that can be used only where it makes sense.
When deployed on Kubernetes, Dapr has a control plane that requires extra resources. The data plane sidecars will also require extra capacity proportional to the application instances. That said, Dapr is written in Go language to have a small footprint. It uses gRPC protocol for more effective sidecar-to-sidecar communication. And Most Dapr operations are network bound with little resource consumption. Yes, Dapr requires extra resources, but its performance and resource consumptions are low and continuously measured and kept under control.
Debugging and testing
Using Dapr will move all external integration points out of your application and help you with the testability of the business logic. But the extra hop can make integration and end-to-end testing more complex and find issues harder. That said, the tooling with debugging container-based applications, and Kubernetes workloads are improving every day including Dapr plugins for IDEs such as VS Code.
Dapr is a developer framework with multifaceted benefits. Its out-of-the-box features help developers integrate services and connect declaratively with third-party systems. Once introduced in the application landscape, Dapr helps operations teams through better observability, increased security and reliability. Dapr is a foundation for platform engineers who want to provide controlled development capabilities to every team in the enterprise. Founded by the creators of Dapr, we at Diagrid help organizations operate Dapr on Kubernetes in a reliable and secure way with minimal effort. If you’d like to learn more about our managed Dapr service, book a free trial for Diagrid Conductor.
However, the 10x benefits alone aren't enough. For an idea to be realized, it must be timely. As Victor Hugo once said, "Nothing is as powerful as an idea whose time has come." Microservices architecture and cloud-native technologies became mainstream so quickly also because of the hardware innovations enabling cheap cloud compute and rapidly changing business needs at the same time. In short, great technology becomes useful when its time has come. Dapr is polyglot like microservices. It's portable like Docker. It's composable like Kubernetes. Dapr is API-driven and declarative, aligned with cloud-native principles and operational practices. It is timely, and naturally complements other cloud-native projects. Its benefits multiply with the rest of the cloud native ecosystem. Dapr is a 10x technology whose time has come.
Subscribe today for exclusive Dapr insights