Quickstart
GRPC is a fully featured Elixir implementation of the gRPC protocol (grpc.io),
enabling efficient communication between services through a unified and
stream-oriented API. It supports all RPC types, friendly error handling, TLS,
interceptors, reflection, and optional HTTP transcoding.
Suitable for both server and client development in pure Elixir, enabling scalable, efficient and type-safe distributed systems.
Main features:
- Unary, Server Streaming, Client Streaming, Bi-directional Streaming RPCs;
- Streaming-first API for every call;
- Interceptors (auth, logging, rate limiting, tracing);
- Error handling with predictable propagation;
- TLS authentication and message compression;
- Connection load balancing strategies (Round Robin, Pick First);
- gRPC Reflection;
- HTTP Transcoding for REST ↔ gRPC compatibility;
Setup
app_root = Path.join(__DIR__, "..")
Mix.install(
[
{:grpc, path: app_root, env: :dev},
{:protobuf, "~> 0.14"}, # optional for importing well-known Google gRPC types
{:grpc_reflection, "~> 0.2"}, # optional for enabling gRPC reflection
{:protobuf_generate, "~> 0.1", only: :dev} # optional for Protobuf code generation with plugins
],
config_path: Path.join(app_root, "config/config.exs"),
lockfile: Path.join(app_root, "mix.lock")
)
Protobuf Service and Messages
defmodule Helloworld.HelloRequest do
use Protobuf, syntax: :proto3
field :name, 1, type: :string
end
defmodule Helloworld.HelloReply do
use Protobuf, syntax: :proto3
field :message, 1, type: :string
end
defmodule Helloworld.Greeter.Service do
use GRPC.Service, name: "helloworld.Greeter"
rpc :SayHello, Helloworld.HelloRequest, Helloworld.HelloReply
end
defmodule Helloworld.Greeter.Stub do
use GRPC.Stub, service: Helloworld.Greeter.Service
end
Logging Interceptor
We create a basic interceptor to log incoming RPC calls.
defmodule LoggingInterceptor do
@behaviour GRPC.Server.Interceptor
require Logger
def init(options), do: options
def call(%GRPC.Server.Stream{} = stream, req, next, _opts) do
Logger.info("RPC: #{stream.service_name}/#{stream.method_name} received request")
next.(stream, req)
end
end
gRPC Server Implementation
defmodule HelloServer do
use GRPC.Server, service: Helloworld.Greeter.Service
def say_hello(%{name: name}, _stream) do
Helloworld.HelloReply.new(message: "Hello, #{name}!")
end
end
Endpoint with Interceptor
defmodule HelloEndpoint do
use GRPC.Endpoint
intercept(LoggingInterceptor)
run(HelloServer)
end
Starting the Server
Here we start the GRPC server under supervision at port 50051.
{:ok, _pid} =
GRPC.Server.Supervisor.start_link(endpoint: HelloEndpoint, port: 50051)
IO.puts("gRPC Server running on port 50051")
Create a Client and Test the RPC
{:ok, _} = GRPC.Client.Supervisor.start_link()
{:ok, channel} = GRPC.Stub.connect("localhost:50051")
request = Helloworld.HelloRequest.new(name: "Hello gRPC Livebook")
{:ok, reply} = Helloworld.Greeter.Stub.say_hello(channel, request)
IO.inspect(reply, label: "Received reply")