# Properties reference, and which project owns what Two things that cause disproportionate confusion: the exact property names, and the fact that **"Spring gRPC" now means two different things with two different version numbers**. --- ## 1. Boot 4.1 integration vs. the Spring gRPC project These are separate artifacts with separate versions, and both are on your classpath. | | **Spring Boot gRPC integration** | **Spring gRPC** | |---|---|---| | Group | `org.springframework.boot` | `org.springframework.grpc` | | Artifacts | `spring-boot-starter-grpc-server`, `spring-boot-starter-grpc-client`, `spring-boot-grpc-server`, `spring-boot-grpc-client`, `spring-boot-grpc-test` | `spring-grpc-core` | | Version here | **4.1.0** (the Boot version) | **1.1.0** | | Owns | auto-configuration, `spring.grpc.*` properties, starters, actuator/health, observation wiring | the programming model: `@GrpcService`, `@GrpcAdvice`, `@GrpcExceptionHandler`, `GrpcChannelFactory`, `@ImportGrpcClients`, interceptor infrastructure | | Managed by | the Boot BOM directly | the Boot BOM, via the `spring-grpc.version` property | Practical consequences: - **Property names (`spring.grpc.*`) come from Boot 4.1**, defined in `GrpcServerProperties` / `GrpcClientProperties` under `org.springframework.boot.grpc.*.autoconfigure`. Version them against your Boot version. - **Annotations and interfaces come from Spring gRPC 1.1.0**, in `org.springframework.grpc.*`. Version them against `spring-grpc.version`. - Boot 4.1 also pins `grpc-java` (**1.80.0** here) and `protobuf-java` (**4.34.2**). Both are older than the newest releases on Maven Central — that is deliberate, and overriding them independently is how you get `NoSuchMethodError` between grpc-java and its Netty shading. ### The older path, and why you will see it in search results Before Boot 4, the community project shipped its own starter: ```xml org.springframework.grpc spring-grpc-spring-boot-starter ``` That artifact stops at **1.0.3** and is not what Boot 4 uses. On Boot 4 use the Boot starters and let the BOM manage everything: ```xml org.springframework.boot spring-boot-starter-grpc-server org.springframework.boot spring-boot-starter-grpc-client ``` Most blog posts and Stack Overflow answers you find will be describing the older artifact. The programming model is largely the same; the dependency coordinates and the property names are not. --- ## 2. Server properties — exact names Read from `spring-boot-grpc-server-4.1.0.jar`'s configuration metadata. This is the complete list. | Property | Notes | |---|---| | `spring.grpc.server.enabled` | | | `spring.grpc.server.port` | `-1` disables the network server (in-process only); `0` picks an ephemeral port | | `spring.grpc.server.address` | | | `spring.grpc.server.inprocess.name` | **`inprocess`, one word — not `in-process`** | | `spring.grpc.server.inbound.message.max-size` | the 4 MB default, for incoming **requests** | | `spring.grpc.server.inbound.metadata.max-size` | header size limit | | `spring.grpc.server.shutdown.grace-period` | | | `spring.grpc.server.keepalive.time` | | | `spring.grpc.server.keepalive.timeout` | | | `spring.grpc.server.keepalive.permit.time` | minimum client ping interval the server tolerates | | `spring.grpc.server.keepalive.permit.without-calls` | | | `spring.grpc.server.keepalive.connection.max-age` | | | `spring.grpc.server.keepalive.connection.max-idle-time` | | | `spring.grpc.server.keepalive.connection.grace-period` | | | `spring.grpc.server.ssl.enabled` / `.bundle` / `.client-auth` / `.secure` | uses Boot SSL bundles | | `spring.grpc.server.health.enabled` | standard gRPC health service | | `spring.grpc.server.health.service` | | | `spring.grpc.server.health.include-overall-health` | | | `spring.grpc.server.health.status.mapping` / `.order` | actuator status → gRPC serving status | | `spring.grpc.server.health.schedule.enabled` / `.delay` / `.period` | | | `spring.grpc.server.health.services.validate-membership` | | | `spring.grpc.server.reflection.enabled` | needed for `grpcurl` without local `.proto` files | | `spring.grpc.server.observation.enabled` | Micrometer observations | | `spring.grpc.server.netty.transport` | | | `spring.grpc.server.netty.domain-socket-path` | | | `spring.grpc.server.servlet.enabled` / `.validate-http2` | gRPC over the servlet container | | `spring.grpc.server.security.csrf.enabled` | | | `spring.grpc.server.factory.enabled` | | ## 3. Client properties — exact names The client side is a **map keyed by channel name**: ``` spring.grpc.client.channel.. ``` **`channel`, singular.** `channels` is wrong and produces no error — see below. | Property | Notes | |---|---| | `spring.grpc.client.channel..target` | **`target`, not `address`** | | `spring.grpc.client.channel..user-agent` | | | `spring.grpc.client.channel..bypass-certificate-validation` | test/dev only | | `spring.grpc.client.channel..default.deadline` | **the default deadline gRPC otherwise lacks** | | `spring.grpc.client.channel..default.load-balancing-policy` | e.g. `round_robin` (default is `pick_first`) | | `spring.grpc.client.channel..inbound.message.max-size` | 4 MB default, for incoming **responses** | | `spring.grpc.client.channel..inbound.metadata.max-size` | | | `spring.grpc.client.channel..keepalive.time` / `.timeout` / `.without-calls` | | | `spring.grpc.client.channel..idle.timeout` | | | `spring.grpc.client.channel..ssl.enabled` / `.bundle` | | | `spring.grpc.client.channel..health.enabled` / `.service-name` | client-side health checking | | `spring.grpc.client.channel..service-config.*` | retry, load balancing, throttling | | `spring.grpc.client.enabled` | | | `spring.grpc.client.inprocess.enabled` | register the in-process channel factory | | `spring.grpc.client.observation.enabled` | | | `spring.grpc.client.channelfactory.enabled` | | `service-config` maps to the gRPC service config record with `loadbalancing`, `method`, `retrythrottling` and `healthcheck` sections. ## 4. The two mistakes, and their symptoms | Wrong | Right | Symptom | |---|---|---| | `spring.grpc.server.in-process.name` | `spring.grpc.server.inprocess.name` | property silently ignored; server never binds in-process | | `spring.grpc.client.channels.x.address` | `spring.grpc.client.channel.x.target` | `UNAVAILABLE: Unable to resolve host x` / `UnknownHostException: x` | The second is the expensive one. An unmatched channel name is handed to the DNS resolver **as a literal target**, so the error names your logical channel as if it were a hostname — and sends you to investigate DNS, service discovery and networking instead of a typo. Both cost real time while building this repository. **Guard against it:** add `spring-boot-configuration-processor` and your IDE will flag unknown `spring.grpc.*` keys. It will not catch a wrong value inside the `channel.` map (the keys there are arbitrary), but it catches everything else.