Istio can proxy both REST (HTTP) and gRPC. The official documentation explains that Istio proxies all TCP traffic, including HTTP, HTTPS, gRPC and plain TCP. However, to use features such as routing or rich metrics, Istio has to know the protocol, and this post is about whether to let it detect that automatically or to state it yourself. What follows summarizes the official Istio document Protocol Selection (checked on 2026-10-20; the version shown on the document is 1.31.2).
How do I tell Istio the protocol?
There are two ways. One is to name the Service port in the form <protocol>[-<suffix>]; the other is to use the appProtocol field on Kubernetes 1.18 or later. If both are set, appProtocol takes priority over the port name.
apiVersion: v1
kind: Service
metadata:
name: orders
spec:
ports:
- name: http-web # set by name: REST
port: 80
- name: grpc-api # set by name: gRPC
port: 9090
- name: backend # set by appProtocol
port: 8081
appProtocol: grpc
In the support table of the official document, grpc and grpc-web are handled the same as http2 by both the sidecar and the gateway. So whether you write grpc or http2 on a gRPC port, it is processed as the same HTTP/2.
Can I leave it to automatic detection?
The sidecar automatically detects HTTP and HTTP/2. If it cannot detect the protocol, it treats that traffic as plain TCP. On a connection that looks like TCP, you cannot use HTTP-level routing and metrics. Also, protocols where the server speaks first (Server First), such as MySQL, do not work with automatic detection, so you must specify them by name. That is why, for services you run, it is safer to name the ports by the convention from the start.
Why look at the gateway separately?
Unlike the sidecar, a gateway does not automatically work out, by default, which kind of HTTP to send to the backend. Without an explicit setting, it forwards every incoming HTTP request as HTTP/1.1. So if the backend is gRPC, you must specify grpc or http2 for it to be forwarded as HTTP/2.
Instead of an explicit setting, you can also give the Service the useClientProtocol option. It makes the gateway forward with the same protocol as the incoming request. However, the official document warns that it can be dangerous for a service that does not support HTTP/2. An HTTPS gateway always advertises support for HTTP/1.1 and HTTP/2, so a modern client can choose HTTP/2 even if the backend cannot speak it.
How is this different from a plain Kubernetes Service?
A plain Kubernetes Service balances load at L4 (per connection). gRPC keeps one connection open for a long time and sends many requests over it, so once a connection attaches to one pod, the requests concentrate there as well. Istio’s proxy (Envoy), on the other hand, knows that gRPC is HTTP/2 and can distribute per request. This is the typical reason to put a mesh in front of gRPC services. This part is not from the document page above; it describes the general difference between L4 and L7 balancing, so check the actual distribution in your own environment.
Frequently asked questions
Is UDP also proxied?
No. According to the document, non-TCP protocols such as UDP are not proxied and behave as usual, without being intercepted by the Istio proxy. So you cannot use them in proxy-only components such as ingress or egress gateways either.
If I set both the port name and appProtocol, which one wins?
appProtocol. The port name steps back when both are defined.
For a gRPC port name, which is better, grpc or http2?
The behavior is the same. In the official table grpc is treated the same as http2, so use grpc, which tells the reader right away that it is gRPC.