# \[Help Wanted\] gRPCClient2.jl: Production Grade gRPC Client

**URL:** <https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141>\
**Category:** Community\
**Tags:** package, announcement\
**Created:** [October 14, 2025, 2:38pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141 "2025-10-14T14:38:41Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 14, 2025, 2:38pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/1 "2025-10-14T14:38:41Z")

</div>

Hello Julia Community,

I have been working on a new gRPC client with an emphasis on production grade performance and reliability. The client is already thread / async safe and uses the fast and up to date 1.0 version of ProtoBuf.jl. There is zero extra memory copying or buffering between the client and libCURL and optimizations to reduce overhead of having many small streams over multiplexed HTTP/2.

Repo: [GitHub - csvance/gRPCClient2.jl: Production Grade gRPC Client for Julia](https://github.com/csvance/gRPCClient2.jl)  
Docs: [gRPCClient2.jl · gRPCClient2](https://csvance.github.io/gRPCClient2.jl/dev/)

The name of the package is just a placeholder while it is under rapid development. The client borrows some code from gRPCClient.jl and Downloads.jl, so thanks to the maintainers/contributors of those packages for helping bootstrap this effort.

Looking for collaborators in general but right now I need the following:

- **general usage testing / feedback on interfaces and API**
- **more test coverage for streaming / test against more gRPC servers than just Python**

Of course I am working through most these myself but I would appreciate any help if you are interested in having a production grade gRPC client in Julia.

The latency / overhead / resource usage is currently quite minimal. Some benchmarks bellow (API not final):

```proto
// Benchmark a unary RPC with small protobufs to demonstrate overhead per request
// subset of grpc_predict_v2.proto for testing

syntax = "proto3";
package inference;

message ServerReadyRequest {}

message ServerReadyResponse
{
  // True if the inference server is ready, false if not ready.
  bool ready = 1;
}

service GRPCInferenceService
{
  // The ServerReady API indicates if the server is ready for inferencing.
  rpc ServerReady(ServerReadyRequest) returns (ServerReadyResponse) {}
}

```

```julia-auto
using ProtoBuf
using BenchmarkTools
using gRPCClient2
using Base.Threads

include("grpc_predict_v2_pb.jl")

const grpc = gRPCCURL()

function bench_ready(n)
    @sync begin

        requests = Vector{gRPCRequest}()
        for i in 1:n
            request = ServerReadyRequest()
            # once we generate bindings from the service definition this will be much cleaner
            req = grpc_unary_async_request(grpc, "grpc://rpctest.local:8001/inference.GRPCInferenceService/ServerReady", request)
            push!(requests, req)
        end

        for req in requests
            response = grpc_unary_async_await(grpc, req, ServerReadyResponse)
        end
    end
end

```

```julia-auto
# Sync usage (must wait for response before sending next request)
@benchmark bench_ready(1)

BenchmarkTools.Trial: 6821 samples with 1 evaluation per sample.
 Range (min … max): 370.152 μs … 6.193 ms ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 520.608 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 722.812 μs ± 671.093 μs ┊ GC (mean ± σ): 0.00% ± 0.00%

  ▂▆█▆▅▄▃▂▂▁ ▁
  ███████████▇▆▅▆▄▄▅▅▄▆▄▄▅▆▆▆▅▂▄▅▅▅▃▅▅▄▅▅▅▅▄▅▄▄▆▆▆▆▆▆▇▇▇▆▅▄▄▄▄▂ █
  370 μs Histogram: log(frequency) by time 3.9 ms <

 Memory estimate: 5.36 KiB, allocs estimate: 109.

```

```julia-auto
# Async usage (send all requests as fast as possible and then wait for all responses)
@benchmark bench_ready(1000)

BenchmarkTools.Trial: 32 samples with 1 evaluation per sample.
 Range (min … max): 149.132 ms … 181.694 ms ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 157.729 ms ┊ GC (median): 0.00%
 Time (mean ± σ): 160.711 ms ± 7.917 ms ┊ GC (mean ± σ): 0.00% ± 0.00%

       ▁ ▄█▁ ▁ ▁                       
  ▆▁▁▆▁█▆▁▆▆▁▁▁▆███▆▁▁▆█▆▆▁▁▁▆▁▁▆▁▁▁▁▁▆▁▁█▁▁▆▁▆▁▁▁▁▁▁▁▁▁▆▁▁▁▁▁▆ ▁
  149 ms Histogram: frequency by time 182 ms <

 Memory estimate: 2.37 MiB, allocs estimate: 54179.

```

Dividing by 1000 we get a mean of 160.711 μs down from 722.812 μs in the sync case, around a 4.5x speedup not having to wait for a response before sending the next request. The ICMP RTT to this server is ~300 μs from my computer on the LAN.

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 16, 2025, 1:53am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/2 "2025-10-16T01:53:31Z")

</div>

Opened a pull request to add support for RPC client stub code generation with ProtoBuf.jl. Depending on how fast I’m able to get services support fully worked out and merged, we could have the v0.1 release in the next few weeks. Tests and CI/precompile infrastructure have been setup and considerable work has been done to smooth out rough edges in terms of having useful exception messages, fixing memory/handle leaks, etc.

I also cleaned up the public interface / API:

```julia
using gRPCClient2

# Include the protobuf definitions and RPC client stubs
include("gen/proto/test_pb.jl")

# Initialize the gRPC package - grpc_shutdown() does the opposite for use with Revise.
grpc_init()

# Create a client from the generated client stub
client = TestService_TestRPC_Client("localhost", 8001; secure=false)

# Sync API
test_response = grpc_sync_request(client, TestRequest(1))

# Async API
requests = Vector{gRPCRequest}()
for i in 1:10
    push!(
        requests, 
        grpc_async_request(client, TestRequest(1))
    )
end

for request in requests
    response = grpc_async_await(client, request)
end

```

Now that the API is relatively stable I’m going to start writing documentation and will continue to stress test the client and fix any remaining undiscovered bugs.

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [October 16, 2025, 5:28am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/3 "2025-10-16T05:28:26Z")

</div>

Looks like some neat work!

> [@csvance](#):
>
> the name of the package is just a placeholder while it is under rapid development

As someone who is specifically not a fan of `xyz2`, `xyz3` packages, are you interested in talking to the gRPCClient.jl folks about potentially replacing it with your package?

---

<div class="post-metadata">

**Author:** ![simsurace](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simsurace/32/30216_2.png) [@simsurace](https://discourse.julialang.org/u/simsurace)\
**Post date:** [October 16, 2025, 6:00am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/4 "2025-10-16T06:00:26Z")

</div>

Nice to see some interest and movement in the gRPC support for Julia. This has long been a stumbling block when integrating Julia services in larger projects, and there aren‘t that many alternatives really, e.g. there is also no AMQP v1 support in the ecosystem either (although I did make a start there, maybe I need to request for help there too). So it is nice to see that someone is willing to push this domain further. Maybe someday we‘ll also have a gRPC server in Julia.

Nice to see some basic integration testing set up as well. Maybe I could help (if I get some spare time, lol) with setting up test servers in a few more languages to test against. At least JS/TS and Go would be nice to catch any inconsistencies in implementations (I heard that there can be some).

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 16, 2025, 6:30am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/5 "2025-10-16T06:30:08Z")

</div>

> [@tecosaur](#):
>
> As someone who is specifically not a fan of `xyz2`, `xyz3` packages, are you interested in talking to the gRPCClient.jl folks about potentially replacing it with your package?

Good idea. Once we are a little farther along with documentation and testing we can open the discussion. I just didn’t want to bother them until it was clear how serious this effort is 😅

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 16, 2025, 6:36am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/6 "2025-10-16T06:36:08Z")

</div>

> [@simsurace](#):
>
> Nice to see some interest and movement in the gRPC support for Julia. This has long been a stumbling block when integrating Julia services in larger projects

Indeed, when I was first trying to adopt Julia for a project at work this ended up being such a large roadblock I almost gave up on the language. So it will be good if no one else ever has to go through that again 😅

> [@simsurace](#):
>
> So it is nice to see that someone is willing to push this domain further. Maybe someday we‘ll also have a gRPC server in Julia.

gRPC server in Julia is on my radar currently, it may be possible to do with nghttp2 which already has a JLL package. Once the client initiative is complete I will look into it more.

> [@simsurace](#):
>
> Maybe I could help (if I get some spare time, lol) with setting up test servers in a few more languages to test against. At least JS/TS and Go would be nice to catch any inconsistencies in implementations (I heard that there can be some).

That would be much appreciated! Get me some spare time too 😄

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 19, 2025, 10:01pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/7 "2025-10-19T22:01:22Z")

</div>

I just merged streaming RPC support. Request, response, and bidirectional are all supported. Test coverage for streaming RPC isn’t nearly as comprehensive as it is for unary RPC currently, but the basics are working.

This should bring us to feature parity with gRPCClient.jl now. I also reached out to the maintainers to ask about doing a 1.X version release with the new codebase.

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [October 28, 2025, 12:15am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/8 "2025-10-28T00:15:54Z")

</div>

Streaming RPC should be stable now after a decent amount of stress testing and bugfixing sessions. We are also now outperforming Python’s gRPC client which tends to have pretty solid performance in my experience.

I ran some benchmarks using the Python gRPC client to compare the overhead between Python’s grpcio package and gRPCClient2.jl. I gave it 24 threads, same as `julia -t auto` on my system when I run `benchmark_workload_smol()` from workloads.jl in the gRPCClient2.jl repo. I’m aware the GIL is a thing, but calling into grpcio releases the GIL so it shouldn’t be a significant bottleneck. Pretty much none of grpcio is written in Python, which is why its fast 😅

```julia-auto
 % uv run grpc_test_client.py 30
average: 7019.47 RPS
std: 202.31 RPS
min: 6153.18 RPS
max: 7278.98 RPS

```

In Julia running the same benchmark with all the recent changes I get (keep in mind this is doing 1000 requests per trial, so we will have divide the results by 1000).

```julia-auto
julia> benchmark_workload_smol()
BenchmarkTools.Trial: 41 samples with 1 evaluation per sample.
 Range (min … max): 108.345 ms … 135.084 ms ┊ GC (min … max): 0.00% … 7.75%
 Time (median): 123.482 ms ┊ GC (median): 0.00%
 Time (mean ± σ): 122.444 ms ± 6.091 ms ┊ GC (mean ± σ): 0.33% ± 1.41%

                               █ ▃▃▃█ █ █ ▃                   
  ▇▁▇▁▁▁▁▇▇▁▁▁▇▁▁▁▁▇▇▇▇▇▁▇▁▇▇▁▁█▁▇▁████▁█▇▁█▇█▁▁▁▁▁▇▇▇▁▁▁▁▇▁▁▁▇ ▁
  108 ms Histogram: frequency by time 135 ms <

 Memory estimate: 4.27 MiB, allocs estimate: 93559.

```

There are 1000 requests per trial, so divide the mean by 1000 and convert to RPS:

```julia-auto
julia> 1 / (0.122444 / 1000)
8166.998791284178

```

We are beating Python by over 1000 RPS on average.

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [November 13, 2025, 4:14pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/9 "2025-11-13T16:14:23Z")

</div>

Does anyone care if we start support with Julia 1.12? It looks like there are some issues specifically with supporting streaming in 1.10/1.11 that were resolved in 1.12. I don’t really have time to dig deeper into it, but as things stand now I plan on supporting all Julia versions \>= 1.12. CI has been updated to test against 1.12 and nightly. I’m also testing as part of a production system that uses gRPC, so far so good.

Sometime in the next few weeks the package will be submitted for registration. I’m hoping that as part of the registration process I can get in contact with the people I need to about the package name + up streaming gRPC codegen into ProtoBuf.jl.

---

<div class="post-metadata">

**Author:** ![xlxs4](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xlxs4/32/224566_2.png) [@xlxs4](https://discourse.julialang.org/u/xlxs4)\
**Post date:** [November 14, 2025, 9:17am UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/10 "2025-11-14T09:17:03Z")

</div>

Thank you very much for taking the time to work on this. Lack of proper gRPC support in Julia was severely limiting IMO

---

<div class="post-metadata">

**Author:** ![ndortega](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ndortega/32/37018_2.png) [@ndortega](https://discourse.julialang.org/u/ndortega)\
**Post date:** [November 19, 2025, 10:01pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/11 "2025-11-19T22:01:03Z")

</div>

@csvance

I’d be super interested in a gRPC server for julia.

When you get this to a decent point I’d love to experiment targeting this as an alternative backend for Oxygen.jl. The package already performs introspection on all inputs and outputs of its handlers so I could potentionally just generate the proto schema & files and hook them into your gRPC server.

I could even find some way to enable both gRPC and HTTP servers to run in the same application, to give people multiple ways to connect to their app

In theory the handlers could look something like:

```julia
# Hypothetical macro for gRPC handlers (auto-generates proto and hooks into some grpc server)
@grpc function add(request::MathRequest)
    result = request.a + request.b
    return MathResponse(result)
end

@grpc function create_peron()
    person = Person("joe", 20)
    return PersonResponse(person)
end

# ...existing code (e.g., @get "/add/{a}/{b}" remains for HTTP)...

serve(port=8080) # HTTP server; gRPC would run separately or integrated

```

Below is the theorectical schema that could be generated from those handlers

```julia-auto
syntax = "proto3";

package oxygen_example;

import "google/protobuf/empty.proto";

message MathRequest {
  double a = 1;
  double b = 2;
}

message MathResponse {
  double result = 1;
}

message Person {
  string name = 1;
  int32 age = 2;
}

message PersonResponse {
  Person person = 1;
}

service OxygenService {
  rpc Add(MathRequest) returns (MathResponse);
  rpc GetPerson(google.protobuf.Empty) returns (PersonResponse);
}

```

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [November 19, 2025, 11:38pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/12 "2025-11-19T23:38:06Z")

</div>

> [@ndortega](#):
>
> I’d be super interested in a gRPC server for julia.

The gRPC server is in development but I’m not making any promises on the timeline yet. The current approach I’m in favor of is to use nghttp2 together with Julia TCP Sockets, but I have no idea how much worse that would perform compared to working directly with Julia’s libuv interface. The reason I like this approach is it could produce something that’s actually useful to many people even before its written in a completely optimal way while not requiring a complete rewrite to take it the rest of the way.

## Update on gRPCClient2.jl

There is now an active pull request / code review in progress for using gRPClient2.jl as the 1.0.0 release for gRPCClient.jl. Not sure exactly when it will be done, but things are looking good so far!

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [December 3, 2025, 3:10pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/13 "2025-12-03T15:10:05Z")

</div>

gRPCClient2.jl is now [gRPCClient.jl with a new home in JuliaIO](https://github.com/JuliaIO/gRPCClient.jl) 🎉

As for actually registering the 1.0.0 release, all that remains is to finish up-streaming code generation support into ProtoBuf.jl.

The test server was rewritten in Go as it turns out some of the benchmarks were bottlenecked by Python’s GIL. Throughput **doubled** in cases with very small messages. @atthom reworked the benchmark scripts to use PrettyTables.jl with proper units showing everything all together nicely.

### `julia -t auto`

```julia-auto
╭──────────────────────────────────┬─────────┬────────┬─────────────┬──────────┬────────────┬──────────────┬─────────┬──────┬──────╮
│ Benchmark │ N │ Memory │ Allocations │ Duration │ Throughput │ Avg duration │ Std-dev │ Min │ Max │
│ │ calls │ MiB │ │ s │ calls/s │ μs │ μs │ μs │ μs │
├──────────────────────────────────┼─────────┼────────┼─────────────┼──────────┼────────────┼──────────────┼─────────┼──────┼──────┤
│ workload_smol │ 91000 │ 3.75 │ 85123 │ 5.03 │ 18079 │ 55 │ 3.96 │ 48 │ 67 │
│ workload_32_224_224_uint8 │ 2900 │ 63.78 │ 9188 │ 5.01 │ 579 │ 1728 │ 97.86 │ 1614 │ 1899 │
│ workload_streaming_request │ 1841000 │ 0.89 │ 6482 │ 4.99 │ 368669 │ 3 │ 1.35 │ 2 │ 21 │
│ workload_streaming_response │ 330000 │ 13.0 │ 27838 │ 5.02 │ 65771 │ 15 │ 5.2 │ 6 │ 37 │
│ workload_streaming_bidirectional │ 405000 │ 1.48 │ 25672 │ 5.0 │ 80948 │ 12 │ 8.52 │ 3 │ 62 │
╰──────────────────────────────────┴─────────┴────────┴─────────────┴──────────┴────────────┴──────────────┴─────────┴──────┴──────╯

```

---

<div class="post-metadata">

**Author:** ![atthom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/atthom/32/7173_2.png) [@atthom](https://discourse.julialang.org/u/atthom)\
**Post date:** [December 3, 2025, 10:13pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/14 "2025-12-03T22:13:13Z")

</div>

Happy to take part in this project @csvance.

This was my first contribution to a FOSS projet and it will not be the last.

---

<div class="post-metadata">

**Author:** ![madppiper](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/madppiper/32/220029_2.png) [@madppiper](https://discourse.julialang.org/u/madppiper)\
**Post date:** [December 31, 2025, 12:14pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/15 "2025-12-31T12:14:55Z")

</div>

That looks incredible, btw! Kudos!

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [January 16, 2026, 8:17pm UTC](https://discourse.julialang.org/t/help-wanted-grpcclient2-jl-production-grade-grpc-client/133141/16 "2026-01-16T20:17:35Z")

</div>

So we got the code generation changes merged into ProtoBuf.jl. Now I am just waiting for a new release to be tagged. Once that is done we can release gRPCClient 1.0.0 😀

So far in our internal test deployment at work the package has been rock solid. Based on Github activity quite a few people are already testing out the package and the feedback has been positive. A decent number of issues have been reported and addressed. At this point everything should be working as expected and the developer experience has had quite a few rough edges ironed out.

The package has also been tested and confirmed working on Julia 1.13-beta1. So we are ready for the next version of Julia 😎
