Recently, I published several videos about Dapr on my Youtube channel. The videos cover the basics of state management, PubSub and service invocation.
The Getting Started with state management and service invocation:
Let’s take a closer look at service invocation with HTTP, Python and Node.
Service Invocation with HTTP

The services you write (here Service A and B) talk to each other using the Dapr runtime. On Kubernetes, you talk to a Dapr sidecar deployed alongside your service container. On your development machine, you run your services via dapr run.
If you want to expose a method on Service B and you use HTTP, you just need to expose an HTTP handler or route. For example, with Express in Node you would use something like:
const express = require('express');
const app = express();
app.post('/neworder', (req, res) => { your code }
You then run your service and annotate it with the proper Dapr annotations (Kubernetes):
annotations:
dapr.io/enabled: "true"
dapr.io/id: "node"
dapr.io/port: "3000"
On your local machine, you would just run the service via dapr run:
dapr run --app-id node --app-port 3000 node app.js
In the last example, the Dapr id is node and we indicate that the service is listening on port 3000. To invoke the method from service A, it can use the following code (Python example shown):
dapr_port = os.getenv("DAPR_HTTP_PORT", 3500)
dapr_url = "http://localhost:{}/v1.0/invoke/node/method/neworder".format(dapr_port)
message = {"data": {"orderId": 1234}}
response = requests.post(dapr_url, json=message, timeout=5)
As you can see, service A does not contact service B directly. It just talks to its Dapr sidecar on localhost (or Dapr on your dev machine) and asks it to invoke the neworder method via a service that uses Dapr id node. It is also clear that both service A and B use HTTP only. Because you just use HTTP to expose and invoke methods, you can use any language or framework.
You can find a complete example here with Node and Python.
Service Invocation with HTTP and GRPC
Dapr has SDKs available for C#, Go and other languages. You might prefer those over the generic HTTP approach. In the case of Go, the SDK uses GRPC to interface with the Dapr runtime. With Dapr in between, one service can use HTTP while another uses GRPC.
Let’s take a look at a service that exposes a method (HelloFromGo) from a Go application. The full example is here. Instead of creating an HTTP route with the name of your method, you use an OnInvoke handler that looks like this (only the start is shown, see the full code):
func (s *server) OnInvoke(ctx context.Context, in *commonv1pb.InvokeRequest) (*commonv1pb.InvokeResponse, error) {
var response string
switch in.Method {
case "HelloFromGo":
response = s.HelloFromGo()
Naturally, you also have to implement an HelloFromGo() method as well:
// HelloFromGo is a simple demo method to invoke
func (s *server) HelloFromGo() string {
return "Hello"
}
Another service can use any language or framework and invoke the above method with a POST to the following URL if the Dapr id of the Go service is goserver:
http://localhost:3500/v1.0/invoke/goserver/method/HelloFromGo
A POST to the above URL tells Dapr to execute the OnInvoke method via GRPC which will run the HelloFromGo function. It is perfectly possible to include a payload in your POST and have the OnInvoke handler to process that payload. The full example is here which also includes sending and processing a JSON payload and sending back a text response. You will need to somewhat understand how GRPC works and also understand protocol buffers. A good book on GRPC is the following one: https://learning.oreilly.com/library/view/grpc-up-and/9781492058328/.
Conclusion
Dapr allows you to choose between HTTP and GRPC interfaces to interact with the runtime. You can choose whatever is most comfortable to you. One team can use HTTP with Python, JavaScript etc… while other teams use GRPC with their language of choice. Whatever you choose, the Dapr runtime will make sure service invocation just works allowing you to focus on the code.