Skip to content

gRPC Interceptor

distlimit provides both Unary and Streaming gRPC server interceptors via the github.com/balramadan/distlimit/middleware/grpc package.


Install gRPC and distlimit using Go Modules:

Terminal window
go get google.golang.org/grpc
go get github.com/balramadan/distlimit

Attach UnaryServerInterceptor and StreamServerInterceptor when initializing your gRPC server:

package main
import (
"net"
"time"
"github.com/balramadan/distlimit"
"github.com/balramadan/distlimit/algorithm/tokenbucket"
"github.com/balramadan/distlimit/driver/memory"
distlimitgrpc "github.com/balramadan/distlimit/middleware/grpc"
"google.golang.org/grpc"
)
func main() {
// 1. Initialize Driver & Limiter (100 requests / minute)
memDriver := memory.New(5 * time.Minute)
limiter, _ := distlimit.New(
memDriver,
distlimit.WithLimit(100),
distlimit.WithWindow(1*time.Minute),
distlimit.WithAlgorithm(tokenbucket.New()),
)
// 2. Register gRPC Interceptors
server := grpc.NewServer(
grpc.UnaryInterceptor(distlimitgrpc.UnaryServerInterceptor(limiter)),
grpc.StreamInterceptor(distlimitgrpc.StreamServerInterceptor(limiter)),
)
lis, _ := net.Listen("tcp", ":50051")
_ = server.Serve(lis)
}

Configure interceptor behavior by passing options into UnaryServerInterceptor(limiter, opts...) or StreamServerInterceptor(limiter, opts...):

Option Type Description
WithTrustedProxies(proxies) []string CIDR blocks or IPs of trusted proxies for parsing x-forwarded-for metadata.
WithKeyExtractor(fn) func(ctx context.Context) string Custom function to extract rate limit key from gRPC context/metadata.
WithRouteLabeling(enable) bool Enables passing gRPC full method (info.FullMethod) into metric labels.

By default, distlimit rate limits requests based on client peer IP address. You can extract custom identifiers like gRPC metadata metadata or auth tokens using WithKeyExtractor:

grpc.UnaryServerInterceptor(
limiter,
distlimitgrpc.WithKeyExtractor(func(ctx context.Context) string {
if md, ok := metadata.FromIncomingContext(ctx); ok {
if tokens := md.Get("authorization"); len(tokens) > 0 {
return "token:" + tokens[0]
}
}
// Fallback to client peer IP address
return distlimitgrpc.ExtractPeerIP(ctx, nil)
}),
)

Unlike HTTP servers that return 429 status codes, gRPC services handle rate limiting via status error responses.

When a client exceeds the allowed quota, distlimit rejects the unary or stream RPC call with gRPC status code codes.ResourceExhausted (numeric code 8):

rpc error: code = ResourceExhausted desc = rate limit exceeded for method /package.Service/Method: try again in 5 seconds