Level Up your Inter-Process Communication with gRPC
By: Developer Daniel
Tags: Rpc, Uds, Ipc, Grpc, Sockets

You are probably reading this thanks to the catchy title. Heck, who doesn’t like leveling up?

In this post we’ll level up (ha! I said it again) our Inter-Process Communication (IPC), specifically giving examples for Linux developers, with the help of gRPC — “a high-performance, open source universal RPC framework” as they clearly state on their website.

After reading this post you’ll hopefully be convinced that gRPC is a superb framework for IPC on the same machine, and not only for distributed computing or microservices in the cloud, as it is widely known for. We’ve even provided an example of gRPC over Unix Domain Sockets (UDS) to help you get started further on.

Does this sound familiar to you?

For those of you who aren’t familiar with Inter-Process Communication, it’s a mechanism that allows processes to communicate and manage their shared data. Some IPC mechanisms include:

Message Passing (Sockets, Unix Domain Sockets, Named Pipes, etc.)

Shared Memory

Here’s an example of Message Passing in action:

As you can see in the diagram, Process A needs to pass objects to Process B. This procedure requires each of the objects to be serialized into a buffer, sent, received, deserialized back, and finally Process B needs to do something with these objects.

What if Process B wants to return an object to Process A? You guessed it! This whole procedure, but backwards.

If the above diagram looks familiar, ask yourself this:

How easy is it to add a new type of object? Does it take minutes? Hours? Days? Is the communication between the processes secure? How long will it take to deploy Process B on another machine, and easily re-implement my transport layer to TCP/IP over sockets instead of UDS? How big of a nuisance will it be to introduce Process C, which expects different objects from Process A? Am I implementing and maintaining ALL this code myself?

If any of these questions made you move uncomfortably in your seat, you may be able to save hours of development time while also improving your project’s architecture along the way.

I know where you’re heading… gRPC! But wait, RPC who?

Remote Procedure Call (RPC) is a form of IPC that enables processes to execute functions in other processes, while passing data back and forth along the way. RPC is no new kid on the block, it has been around for ages. It can be used for processes on the same machine, as well as for communication between machines. There are many frameworks and libraries implementing RPC, supporting a variety of programming languages performing the serialization differently. While most implementations over the years have been hit-or-miss, gRPC hasn’t been one of them.

So, what’s so special about gRPC?

gRPC finds its roots in Google’s implementation of Protocol Buffers, known as Protobuf, a method of serializing structured data. It was designed to be faster and smaller than XML and very simple; an interface description language that describes the structure of the data it serializes.

gRPC adds the HTTP2 transport layer, which addresses several issues with the former HTTP1.1 protocol. Thus, gRPC performs better than other alternatives based on the HTTP1.1 protocol. Among gRPC’s many features you can find bidirectional streaming, blocking and non-blocking transmissions, timeouts, SSL/TLS authentication & encryption, and more. Since it was open-sourced in 2015 by Google, its most common use case is microservice style architectures.

The ‘g’ in gRPC surprisingly does not stand for “Google”, the original developers of the library, but the maintainers find a different ‘g’ related word for every version, as can be seen here.

Some standout advantages include:

Both messages and services are defined using a simple agreed-upon-by-all-parties definition language. This design allows an easy way to decouple the dependencies between processes. Thus, the API is always straight-forward and clutter-free.

The client and server implementations can be generated natively, in over 10 different languages: C#, C++, Dart, Go, Java, Kotlin, Node.js, Objective-C, PHP, Python and Ruby.

There is a large community developing tools and plugins. A list of awesome gRPC resources can be found here.

While many know gRPC for its HTTP transport, it can also be used for transporting over UDS.

This means that if you’re a security-conscious developer, as I’m sure you are, you will be able to configure the communication over a Unix Domain Socket. This grants you better control of permissions and security, as Unix file permissions apply. This slick feature doesn’t necessarily come out of the box in all languages. We’ve implemented an example of the popular gRPC “Hello World” over UDS in C++. You can find the greeter_client.cc code here, and the greeter_server.cc code here. Additional plugins can be added it, such as the SSL/TLS encryption, to secure your connection even further.

So, to answer our initial questions above:

It’s SUPER easy to add new objects — it’s a matter of minutes to implement! Simply define them using the interface definition language. It allows setting up state of the art security using SSL/TLS. The distance between HTTP transport and UDS are only few lines of code away. Simply define a new API using the definition language, compile, and use the automatically generated client and server implementations — can’t get easier than that. Since most of the code is generated, you only need to maintain the API. Serialization, deserialization and synchronizing between shared object interfaces is a thing of the past.

I’m convinced! How do I start?

Refactoring infrastructure is easier said than done, but we’ve gathered a few tips for you from our experience when leveling up our IPC.

Don’t try moving trees at first — plant the seeds and wait. When developing a new feature, see how you can decouple its logic. If you can decouple it from the rest of your project successfully, go ahead and design its API with your project, using the interface description language. Plan which process contains the client, while the other contains the server.

See whether gRPC works for you. In some cases, a simple send() — recv() or shared memory can suffice.

Once you’ve got the hang of it, slowly transition already decoupled processes to communicate using gRPC.

If you develop in C++ and have your testing tools written in C# or Python, you’ll find out how well multi-language is supported in gRPC. This way you can fully test your processes without necessarily needing to re-implement everything.

There are various circumstances errors raised, and lots of RPC execution status codes. You’ll find that they can be very informative — make sure you handle them well.

Before we part ways — any final words for the road ahead?

gRPC can fit many use cases, even if not from the get-go. In this article, I’ve talked about how it can be used as a replacement for plain IPC messaging implementations you may have in your code. An example for gRPC over UDS has been presented, demonstrating how a gRPC-based server can accept connections over a socket with a file descriptor.

Many projects maintain a lot of code that can be substituted with modern RPC implementations, such as gRPC that can provide a lot more. It does not fit every use case, but it’s one step closer to breaking your monolith into microservices (a more modern approach).



If you’re interested in distributed computing, you’d know that REST API alternatives exist — but in the world of microservices, gRPC is leading the way. Even if you’re not interested in distributed computing and would like to keep your project in one machine — gRPC still has a lot to offer.

We are still decoupling our features one after the other, using gRPC for IPC communication, and are satisfied so far. Decoupling the features allows us to test each feature alone, implementing an isolated “mock” client that interacts with it. Hopefully our experience can be of use to your projects as well. Fare well!