The state of gRPC in the browser

A technical analysis of the gRPC-Web ecosystem

gRPC 1.0 was released in August 2016 and has since grown to become one of the premier technical solutions for application communications. It has been adopted by startups, enterprise companies, and open source projects worldwide. Its support for polyglot environments, focus on performance, type safety, and developer productivity has transformed the way developers design their architectures.

So far the benefits have largely only been available to mobile app and backend developers, whilst frontend developers have had to continue to rely on JSON REST interfaces as their primary means of information exchange. However, with the release of gRPC-Web, gRPC is poised to become a valuable addition in the toolbox of frontend developers.

In this post, I’ll describe some of the history of gRPC in the browser, explore the state of the world today, and share some thoughts on the future.


In the summer of 2016, both a team at Google and Improbable1 independently started working on implementing something that could be called “gRPC for the browser”. They soon discovered each other’s existence and got together to define a spec2 for the new protocol.

The gRPC-Web Spec

It is currently impossible to implement the HTTP/2 gRPC spec3 in the browser, as there is simply no browser API with enough fine-grained control over the requests. For example: there is no way to force the use of HTTP/2, and even if there was, raw HTTP/2 frames are inaccessible in browsers. The gRPC-Web spec starts from the point of view of the HTTP/2 spec, and then defines the differences. These notably include:

  • Supporting both HTTP/1.1 and HTTP/2.
  • Sending of gRPC trailers at the very end of request/response bodies as indicated by a new bit in the gRPC message header4.
  • A mandatory proxy for translating between gRPC-Web requests and gRPC HTTP/2 responses.

The Tech

The basic idea is to have the browser send normal HTTP requests (with Fetch or XHR) and have a small proxy in front of the gRPC server to translate the requests and responses to something the browser can use.

The role of the gRPC-Web proxy

The Two Implementations

The teams at Google and Improbable both went on to implement the spec in two different repositories5,6, and with slightly different implementations, such that neither was entirely conformant to the spec, and for a long time neither was compatible with the other’s proxy7,8.

The Improbable gRPC-Web client9 is implemented in TypeScript and available on npm as @improbable-eng/grpc-web10. There is also a Go proxy available, both as a package that can be imported into existing Go gRPC servers11, and as a standalone proxy that can be used to expose an arbitrary gRPC server to a gRPC-Web frontend12.

The Google gRPC-Web client13 is implemented in JavaScript using the Google Closure library14 base. It is available on npm as grpc-web15. It originally shipped with a proxy implemented as an NGINX extension16, but has since doubled down on an Envoy proxy HTTP filter17, which is available in all versions since v1.4.0.

Feature Sets

The gRPC HTTP/2 implementations all support the four method types: unary, server-side, client-side, and bi-directional streaming. However, the gRPC-Web spec does not mandate any client-side or bi-directional streaming support specifically, only that it will be implemented once WHATWG Streams18 are implemented in browsers.

The Google client supports unary and server-side streaming, but only when used with the grpcwebtext mode. Only unary requests are fully supported in the grpcweb mode. These two modes specify different ways to encode the protobuf payload in the requests and responses.

The Improbable client supports both unary and server-side streaming, and has an implementation that automatically chooses between XHR and Fetch based on the browser capabilities.

Here’s a table that summarizes the different features supported:

Client / Feature Transport Unary Server-side streams Client-side & bi-directional streaming
Improbable Fetc️h/XHR ️ ✔️ ✔️ 19
Google (grpcwebtext) XHR ️ ✔️ ✔️
Google (grpcweb) XHR ️ ✔️ 20

For more information on this table, please see my compatibility test repo on github.

The compatibility tests may evolve into some automated test framework to enforce and document the various compatibilities in the future.

Compatibility Issues

Of course, with two different proxies also come compatibility issues. Fortunately, these have recently been ironed out, so you can expect to use either client with either proxy.

The Future

The Google implementation announced version 1.0 and general availability in October 201821 and has published a roadmap of future goals22, including:

  • An efficient JSON-like message encoding
  • In-process proxies for Node, Python, Java and more
  • Integration with popular frameworks (React, Angular, Vue)
  • Fetch API transport for memory efficient streaming
  • Bi-directional steaming support

Google is looking for feedback on what features are important to the community, so if you think any of these are particularly valuable to you, then please fill in their survey23.

Recent talks between the two projects have agreed on promoting the Google client and Envoy proxy as preferred solutions for new users. The Improbable client and proxy will remain as alternative implementations of the spec without the Google Closure dependency, but should be considered experimental. A migration guide will be produced for existing users to move to the Google client, and the teams are working together to converge the generated APIs.


The Google client will continue to have new features and fixes implemented at a steady pace, with a team dedicated to its success, and it being the official gRPC client. It doesn’t have Fetch API support like the Improbable client, but if this is an important feature for the community, it will be added. The Google team and the greater community are collaborating on the official client to the benefit of the gRPC community at large. Since the GA announcement the community contributions to the Google gRPC-Web repo has increased dramatically.

When choosing between the two proxies, there’s no difference in capability, so it becomes a matter of your deployment model. Envoy will suit some scenarios, while an in-process Go proxy has its own advantages.

If you’re getting started with gRPC-Web today, first try the Google client. It has strict API compatibility guarantees and is built on the rock-solid Google Closure library base used by Gmail and Google Maps. If you need Fetch API memory efficiency or experimental websocket client-side and bi-directional streaming, the Improbable client is a good choice, and it will continue to be used and maintained by Improbable for the foreseeable future.

Either way, gRPC-Web is an excellent choice for web developers. It brings the portability, performance, and engineering of a sophisticated protocol into the browser, and marks an exciting time for frontend developers!


  19. The Improbable client supports client-side and bi-directional streaming with an experimental websocket transport. This is not part of the gRPC-Web spec, and is not recommended for production use.
  20. grpcweb allows server streaming methods to be called, but it doesn’t return data until the stream has closed.


Monday, Apr 1, 2019

is doing gRPC over websockets an option? a pure JS implementation of gRPC could use a websocket as transport and still do all the TLS stuff regardless of the underlying socket?
Reply to Ruben

In reply to Ruben
Monday, Apr 1, 2019

gRPC over websockets is possible with a properly instrumented server, see for an example implementation of this (using Go and webassembly). However, this is problematic since it means implementing TCP over websockets over TCP, a huge inefficiency. The gRPC-Web spec tries to make the best gRPC-equivalent transport possible from the browser. When we get websockets over HTTP/2 in the browser the spec may be expanded to include this as a possible transport, but today it is pretty pointless.

In reply to Ruben
Tuesday, Apr 2, 2019

yea I was actually playing around with go wasm for this as well!

the interwebs says a lot about tcp over tcp being “bad”; . if it’s possible to avoid/mitigate these tcp meltdown issues, it seems like doing grpc over a websocket connection is doable though.

and you can actually configure custom SSL certs on the client-side, which is impossible any other way in a browser!

the ~10% overhead of doing tcp over tcp might be acceptable in many scenarios I think? considering networking is rarely the biggest chunk of response time?

In reply to Ruben
Tuesday, Apr 2, 2019

There are benefits to be sure, but this is so far removed from the rest of the existing web ecosystem as to be mostly academic in importance I think. You can do it today in your own stack if you want to, but you’ll end up with huge webassembly binaries (because now the client needs the whole http2-over-tcp stack compiled in) and a Go gRPC server that can’t talk to normal gRPC servers. It’s certainly exciting as a tech demo, but for wider adoption I think the route that the gRPC-Web team has adopted with the spec is the right one.
Reply to Thread

Add a comment