{"id":50326369,"url":"https://github.com/fly-apps/grpc-service","last_synced_at":"2026-05-29T06:30:38.050Z","repository":{"id":42750499,"uuid":"276867817","full_name":"fly-apps/grpc-service","owner":"fly-apps","description":"Running gRPC services on Fly.io","archived":false,"fork":false,"pushed_at":"2026-04-17T03:17:34.000Z","size":791,"stargazers_count":8,"open_issues_count":19,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-05-28T14:28:59.866Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fly-apps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-03T10:01:02.000Z","updated_at":"2026-01-19T22:34:49.000Z","dependencies_parsed_at":"2022-09-15T17:13:29.494Z","dependency_job_id":null,"html_url":"https://github.com/fly-apps/grpc-service","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fly-apps/grpc-service","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fly-apps%2Fgrpc-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fly-apps%2Fgrpc-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fly-apps%2Fgrpc-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fly-apps%2Fgrpc-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fly-apps","download_url":"https://codeload.github.com/fly-apps/grpc-service/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fly-apps%2Fgrpc-service/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33640627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T06:30:36.657Z","updated_at":"2026-05-29T06:30:38.030Z","avatar_url":"https://github.com/fly-apps.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gRPC \u0026 gRPC-Web Services on Fly.io\n\n\u003e Run gRPC \u0026 gRPC-Web services close to users with [Fly](https://fly.io/).\n\n## Overview\n\n\u003c!---- cut here ---\u003e\n\nThis application demonstrates how to run a gRPC service on Fly.io. Fly runs tiny virtual machines at edge datacenters close to your users.\n\ngRPC is designed for fast, low overhead services with client and server code generation tools for many languages and VMs.\n\ngRPC servers run their own HTTP/2-based protocol, so they offer excellent performance benefits. This will not work out of the box with most hosting platforms. In fact, you can't even call the service directly from a web browser. In this example, we'll consume the gRPC service with a special web adapter. This allows you to create the client stubs and use them in browser-based JavaScript.\n\nThis example uses the [gRPC](https://grpc.io) libraries for the main gRPC service and [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) for browser support.\n## What we'll deploy\n\nSince this is an example, we'll write a quick gRPC service definition in [`hello.proto`](https://github.com/fly-examples/grpc-service/blob/master/hello.proto) that has the following methods:\n\n```protobuf\nservice MainService {\n  rpc Hello(Empty) returns (Greeting);\n  rpc Clock(Empty) returns (stream Time);\n}\n```\n\n## Deploying the gRPC service to Fly\n\n- Install [flyctl](https://fly.io/docs/getting-started/installing-flyctl/)\n- Login to Fly using `fly auth login`\n- Create and deploy the app with `fly launch`\n## Using the gRPC service\n\nWith gRPC, you'll usually use the generated client libraries in the language of your choice.\n\nTo make sure our service is working, we'll use the [`grpcurl`](https://github.com/fullstorydev/grpcurl) tool:\n\n```shell\ngrpcurl -proto hello.proto grpc-test.fly.dev:443 MainService/Hello\n```\n\nYou can also test streaming by calling the `Clock` method. It sends a timestamp every second:\n\n```shell\ngrpcurl -proto hello.proto grpc-test.fly.dev:443 MainService/Clock\n```\n## What's Happening Inside\n\nThe gRPC servers that we're running have one special feature that makes them difficult to deploy on many systems – they use the relatively new HTTP/2 protocol with a special feature called HTTP Trailers. Most HTTP/2 load balancers will terminate the HTTP/2 connection at the load balancer, and then make a more compliant HTTP/1.1 connection on the backend to the application server. This won't work with gRPC.\n\nLuckily, Fly supports connecting to your service using HTTP/2, with the following configuration in your `fly.toml`:\n\n```toml\n[http_service]\n  internal_port = 54321\n  force_https = true\n  auto_stop_machines = 'stop'\n  auto_start_machines = true\n  min_machines_running = 0\n  processes = ['app']\n\n [http_service.http_options]\n  h2_backend = true\n\n[http_service.tls_options]\n  alpn = [\"h2\"]\n```\n\nOnce the TCP request reaches your gRPC application, the server will then take over and provide threading / event loop / goroutine management, depending on your chosen language, along with serialization and deserialization.\n\n## Using the Web Proxy\n\nBecause the gRPC services uses HTTP/2, you can't make requests to it from inside a browser — there are currently no browser APIs that allow direct and full control of a HTTP/2 connection. To enable use inside a browser, there's a [gRPC-Web](https://grpc.io/docs/languages/web/) specification that converts a normal HTTP/1.1 request to and from the gRPC HTTP/2 format. Multiple proxy servers that implement the spec are available, like [Envoy](https://grpc.io/docs/languages/web/basics/#configure-the-envoy-proxy) and [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) (which we've deployed here). We've generated JS code for our gRPC definition using the instructions [on the official gRPC-Web example page](https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/helloworld#generate-protobuf-messages-and-client-service-stub), so let's see how to use it.\n\n In the `web-proxy` folder, the [`client.js`](https://github.com/fly-examples/grpc-service/blob/master/web-proxy/client.js) file calls the two methods of our service and writes the output into `console.log`. You can change the following [line](https://github.com/fly-examples/grpc-service/blob/master/web-proxy/client.js#L4):\n\n```js\n var client = new MainServiceClient('https://grpc-web-proxy-test.fly.dev:443');\n```\n\nto update it with your web proxy app's hostname and then run:\n\n```shell\nnpm install\nnpx webpack client.js\nopen index.html\n```\n\nThis will re-compile the client and open up your browser, where the method repsonses are being printed into the console.\n\nYou'll notice that the clock stops streaming after exactly 10 seconds – this is based on a [flag](https://github.com/improbable-eng/grpc-web/blob/b16a11b6e855a48b6bc6e369a85f3d46fcfe1a77/go/grpcwebproxy/main.go#L45) in the proxy configuration that you'll want to set if your services have longer-running methods. For example, you can set them to 1 hour by adding `--server_http_max_write_timeout=3600` and `--server_http_max_read_timeout=3600` to the `ENTRYPOINT` command in [`web-proxy/Dockerfile`](https://github.com/fly-examples/grpc-service/blob/master/web-proxy/Dockerfile#L40).\n\n## How Does Fly Fit Into This?\n\nWhile gRPC works really well when communicating between servers on the same rack or same datacenter, the principles it uses apply equally well to clients on websites or mobile devices. The HTTP/2 communication channel remains open as much as possible to provide a low-latency and low-energy way to speak to your server, and the underlying [Protocol Buffers](https://developers.google.com/protocol-buffers) serialization/de-serialization system is very low-overhead, so it's great for cellular or metered-bandwidth connections.\n\nRunning your backend services on Fly lets you put your services really close to every user in your global client base. If your data is in a central location, your services can use the local Redis cache that Fly provides at each edge location to cache data, and broadcast changes or invalidations via the [global Redis command broadcast](https://fly.io/docs/redis/#managing-redis-data-globally). There are also data solutions from other cloud providers like [DynamoDB Global Tables](https://aws.amazon.com/dynamodb/global-tables/) (NoSQL), [Aurora Multi-Master](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html) (SQL) or [Google Cloud Spanner](https://cloud.google.com/spanner) (SQL) that can help spread your data across the world and closer to your application servers.\n\nThe reduced latency from having your servers close to your clients is especially useful in gRPC where you want all your calls to finish as quickly as possible. If your clients are mobile applications, they'll benefit even more from the latency reduction when they're running on cellular networks, where bandwidth is low and re-connections are common.\n\n## Testing gRPC performance with `ghz`\n\nBecause gRPC applications use a special wire protocol, we can't use `cURL`, `wget` or `siege` like we would on normal servers. Instead, there are special gRPC-aware tools like [ghz](https://ghz.sh) that work great. After you enable the Fly regions you'd like to run your service in and set the container CPU \u0026 memory configuration to the size you need, you can use `ghz` to test your service:\n\n```\nghz grpc-test.fly.dev:443 --call=MainService/Hello --proto=hello.proto\n```\n\nKeep in mind that this test will run against your closest enabled Fly region, which may or may not be the region that your users will use. gRPC testing also works a little different, because a single HTTP/2 connection is re-used across many requests. Testing against dummy methods that don't do much is really just a test of single connection bandwidth. The best way to make sure your service is running great would be to enable the instrumentation provided in your client and service libraries and exercise your service in a real-world scenario.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffly-apps%2Fgrpc-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffly-apps%2Fgrpc-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffly-apps%2Fgrpc-service/lists"}