Modern applications are moving toward microservices and high-performance communication. If you're still using REST for everything, it might be time to explore a faster and more efficient alternative: gRPC.
In this article, weโll break down what gRPC is, why itโs powerful, and how to build your first service using Golang.
What is gRPC?
gRPC (Google Remote Procedure Call) is a high-performance RPC framework developed by Google. It allows services to communicate directly using function calls instead of traditional HTTP/JSON APIs.
Instead of:
GET /users/1
You do:
userService.GetUser(ctx, &UserRequest{Id: 1})
Why Use gRPC?
1. High Performance
- Uses HTTP/2
- Binary serialization with Protocol Buffers (Protobuf)
- Faster and more efficient than REST/JSON
2. Strongly Typed APIs
- Contracts are defined using
.protofiles - No ambiguity between services
3. Streaming Support
- Client streaming
- Server streaming
- Bidirectional streaming
Perfect for real-time systems (chat apps, live data, etc.)
4. Multi-language Support
- Works with Go, JavaScript, Python, Java, etc.
Key Concepts
1. Protocol Buffers (Protobuf)
This is where you define your API structure.
Example:
syntax = "proto3";
package user;
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
message UserRequest {
int32 id = 1;
}
message UserResponse {
int32 id = 1;
string name = 2;
}
2. Code Generation
From the .proto file, you generate Go code:
protoc --go_out=. --go-grpc_out=. user.proto
Building a gRPC Server in Go
Step 1: Install Dependencies
go mod init grpc-demo
go get google.golang.org/grpc
go get google.golang.org/protobuf
Step 2: Implement the Server
package main
import (
"context"
"log"
"net"
pb "grpc-demo/user"
"google.golang.org/grpc"
)
type server struct {
pb.UnimplementedUserServiceServer
}
func (s *server) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
return &pb.UserResponse{
Id: req.Id,
Name: "Kamal",
}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatal(err)
}
grpcServer := grpc.NewServer()
pb.RegisterUserServiceServer(grpcServer, &server{})
log.Println("gRPC server running on port 50051...")
if err := grpcServer.Serve(lis); err != nil {
log.Fatal(err)
}
}
Building a gRPC Client in Go
package main
import (
"context"
"log"
"time"
pb "grpc-demo/user"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client := pb.NewUserServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
res, err := client.GetUser(ctx, &pb.UserRequest{Id: 1})
if err != nil {
log.Fatal(err)
}
log.Println("User:", res.Name)
}
gRPC vs REST
| Feature | gRPC | REST |
|---|---|---|
| Protocol | HTTP/2 | HTTP/1.1 |
| Data Format | Binary (Protobuf) | JSON |
| Performance | Faster | Slower |
| Streaming | Native support | Limited |
| Browser Support | Limited | Excellent |
When NOT to Use gRPC
- Public APIs consumed by browsers
- Simple CRUD services
- When debugging via browser is important
gRPC shines in internal microservices communication
Pro Tips
- Use gRPC Gateway if you need REST + gRPC
- Add interceptors for logging/authentication
- Combine with Docker for microservices
- Use TLS in production
Final Thoughts
gRPC with Go is a powerful combination for building fast, scalable, and modern backend systems. If you're targeting microservices or high-performance systems, it's a must-learn tool.
Top comments (0)