Class GrpcServerFlowControlCustomizer

java.lang.Object
ai.pipestream.dynamic.grpc.server.GrpcServerFlowControlCustomizer
All Implemented Interfaces:
io.quarkus.grpc.api.ServerBuilderCustomizer

@ApplicationScoped public class GrpcServerFlowControlCustomizer extends Object implements io.quarkus.grpc.api.ServerBuilderCustomizer
Customizes the gRPC server builder to set the HTTP/2 flow control window for optimal large message throughput.

This customizer is automatically discovered by Quarkus CDI and applied during server initialization. It reads the flow control window from quarkus.grpc.server.flow-control-window configuration property and applies it to the underlying NettyServerBuilder when using separate server mode (quarkus.grpc.server.use-separate-server=true).

Why This Is Critical

The default HTTP/2 flow control window of 64KB causes severe throughput bottlenecks for large messages:

  • Default (64KB): 5-10 MB/s throughput
  • Optimized (100MB): 250-370 MB/s throughput

For a 250MB message, the default window requires ~4,000 round-trips, while a 100MB window allows the entire message to be pipelined with minimal waiting.

Configuration


 # Enable separate server mode (REQUIRED for flow control tuning)
 quarkus.grpc.server.use-separate-server=true
 
 # Set flow control window (default: 100MB)
 quarkus.grpc.server.flow-control-window=104857600
 

How It Works

  1. Quarkus discovers this bean via CDI (@ApplicationScoped)
  2. During server initialization, Quarkus calls customize(GrpcServerConfiguration, ServerBuilder)
  3. If using VertxServerBuilder (separate server mode), we access the underlying NettyServerBuilder
  4. We set the initial flow control window via NettyServerBuilder.initialFlowControlWindow(int)
  5. The setting is applied before the server starts

Why Separate Server Mode?

Unified server mode (use-separate-server=false) does NOT support HTTP/2 flow control window configuration. The unified Vert.x HTTP server does not expose flow control window settings through GrpcServerOptions, and while HttpServerOptionsCustomizer exists, it does not reliably work for gRPC traffic in unified mode.

Separate server mode (Netty-based) provides:

  • ✅ Full control over HTTP/2 settings via NettyServerBuilder
  • ✅ Proven performance: 250-370 MB/s throughput (tested)
  • ✅ Direct access to all gRPC/HTTP/2 configuration options
  • ⚠️ Trade-off: Uses a separate port (acceptable for gRPC services)

See UNIFIED_SERVER_LIMITATIONS.md for detailed analysis of why unified mode doesn't work.

Since:
0.2.6
See Also:
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    customize(io.quarkus.grpc.runtime.config.GrpcServerConfiguration config, io.grpc.ServerBuilder builder)
    Customizes the gRPC server builder to set the flow control window.
    int
    Returns the priority for this customizer.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface io.quarkus.grpc.api.ServerBuilderCustomizer

    customize
  • Constructor Details

    • GrpcServerFlowControlCustomizer

      public GrpcServerFlowControlCustomizer()
  • Method Details

    • customize

      public void customize(io.quarkus.grpc.runtime.config.GrpcServerConfiguration config, io.grpc.ServerBuilder builder)
      Customizes the gRPC server builder to set the flow control window.

      This method is called by Quarkus during server initialization when using separate server mode (use-separate-server=true). It reads the flow control window from configuration and applies it to the NettyServerBuilder.

      Specified by:
      customize in interface io.quarkus.grpc.api.ServerBuilderCustomizer
      Parameters:
      config - The gRPC server configuration
      builder - The server builder instance (must be VertxServerBuilder for this to work)
    • priority

      public int priority()
      Returns the priority for this customizer.

      Higher priority customizers are applied later. We use a high priority (100) to ensure this runs before other customizers that might depend on flow control settings being applied.

      Specified by:
      priority in interface io.quarkus.grpc.api.ServerBuilderCustomizer
      Returns:
      The priority (100)