Skip to content

gRPC

gRPC is Gortexa’s native protocol. External connections arrive on the same h2c port; the mux dispatches on Content-Type: application/grpc to grpc-go’s ServeHTTP mode.

Services are defined in proto. The built-in sample resource:

service ResourceService {
rpc CreateResource(CreateResourceRequest) returns (Resource);
rpc GetResource(GetResourceRequest) returns (Resource);
rpc ListResources(ListResourcesRequest) returns (ListResourcesResponse);
rpc UpdateResource(UpdateResourceRequest) returns (Resource);
rpc DeleteResource(DeleteResourceRequest) returns (google.protobuf.Empty);
}

gortexa regen writes stubs to gen/; logic implementations live in internal packages. The two never mix.

For local grpcurl testing, enable reflection first (it is off by default):

Terminal window
GORTEXA_SERVER__REFLECTION=true gortexa run
Terminal window
grpcurl -plaintext \
-H 'authorization: Bearer <token>' \
-d '{"id":"x"}' \
localhost:8080 myapp.resource.v1.ResourceService/GetResource

myapp is the scaffolded project’s proto namespace (derived from the module path since v0.28.0, see Create a project); when running the sample inside a framework checkout the service is resource.v1.ResourceService.

Without a token you get UNAUTHENTICATED: auth treats all three protocols the same way.

The three-state health model maps to the standard gRPC Health protocol. Register real dependency checks with app.Health().Register(...) so /readyz and gRPC Health reflect actual DB, cache and MQ reachability. Each check runs under a 5-second timeout, so one slow dependency cannot stall the whole query. Health.Watch is exempt from both auth and load shedding (a probe must still answer while the server sheds), so it carries its own ceiling: at most 1,024 concurrent watch streams, beyond which Watch returns RESOURCE_EXHAUSTED. All watchers share one registry evaluation per one-second interval, so N streams do not mean N dependency pings. Registering the same check name twice panics — a boot-time wiring mistake should be loud rather than silently leaving a dependency unmonitored; use Replace(name, check) when substitution is the actual intent.

gRPC reflection is off by default. Enable it via config or an environment variable when needed:

Terminal window
GORTEXA_SERVER__REFLECTION=true

Enabling it exempts /grpc.reflection. from both auth and the in-flight budget (a stream holds its slot for its whole lifetime; exempting auth but not the count would let an unauthenticated client pin the budget). Keep it off in production — see Deployment.

Yes. Since Go 1.24, http.Server.Protocols supports h2c natively, and that is what Gortexa uses — no deprecated x/net/http2/h2c wrapper. Terminate TLS in front of it in production.

Should gRPC reflection be enabled in production?

Section titled “Should gRPC reflection be enabled in production?”

No. Enabling it exempts /grpc.reflection. from both auth and the in-flight budget, which publishes your full service schema to unauthenticated callers. It is off by default and intended for dev tooling such as buf curl --reflect.

Why do my keepalive settings have no effect?

Section titled “Why do my keepalive settings have no effect?”

External gRPC on the shared h2c port runs in grpc-go’s ServeHTTP handler mode, where transport-level options (KeepaliveParams, MaxStreams and friends) are inert. Split gRPC onto its own listener if you need keepalive enforcement.