Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
15 Sep 2025 · 5 min read ·Article 99 / 110
Go

99. Case Study: Admin Dashboard Built with grpc-gateway

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

99. Case Study: Admin Dashboard Built with grpc-gateway

The admin dashboard is the beating heart of managing large-scale applications. Behind its buttons and statistics tables lies a real architectural challenge: how backend services communicate with one another. One modern way to build a robust yet developer-friendly API is grpc-gateway. In this case study, we will dig into how to build an admin dashboard powered by grpc-gateway, complete with design considerations, code examples, flow simulations, and best practices.


Introduction: When REST Is No Longer Enough

Many applications start out with a REST API. But as data volume grows, real-time needs emerge, and the demand for multi-platform integration increases, this protocol starts to feel inefficient. gRPC, built on HTTP/2 and Protocol Buffers, offers performance and type safety. However, pure gRPC is not yet universal: not every frontend is ready to speak gRPC natively. This is exactly the gap that grpc-gateway fills: an automatic bridge from gRPC to a RESTful API.


Case Study: A User Performance Admin Dashboard

Suppose we have a SaaS application with an admin team that manages users, monitors usage, and intervenes whenever an anomaly occurs. We want an admin dashboard that:

  • Displays user statistics in real time.
  • Performs user CRUD with fast responses.
  • Is accessible from a web frontend (through RESTful endpoints).
  • Has an efficient backend, a well-designed schema, and is easy to scale.

Architecture Choices

LayerChosen StackRationale
FrontendReact + fetchFamiliar, REST endpoint ready
API Gatewaygrpc-gateway (Go)Translates HTTP(JSON) <-> gRPC
BackendgRPC Microservices (GoLang)High-perf, strong typing
StoragePostgreSQLConsistent, great for analytics

Protobuf Definition: Define the API Once for Everyone

gRPC starts from a single source of truth: the .proto file. For example, user.proto:

proto
 1syntax = "proto3";
 2
 3package admin;
 4
 5service UserService {
 6    rpc GetUserStats (StatsRequest) returns (StatsResponse) {
 7        option (google.api.http) = {
 8            get: "/admin/users/stats"
 9        };
10    }
11
12    rpc ListUsers (ListUsersRequest) returns (ListUsersResponse) {
13        option (google.api.http) = {
14            get: "/admin/users"
15        };
16    }
17
18    rpc CreateUser (CreateUserRequest) returns (User) {
19        option (google.api.http) = {
20            post: "/admin/users"
21            body: "*"
22        };
23    }
24
25    rpc DeleteUser (DeleteUserRequest) returns (Empty) {
26        option (google.api.http) = {
27            delete: "/admin/users/{id}"
28        };
29    }
30}
31
32message StatsRequest {}
33message StatsResponse {
34    int32 active_user_count = 1;
35    int32 total_user_count = 2;
36}
37
38message User {
39    string id = 1;
40    string name = 2;
41    string email = 3;
42}
43
44message ListUsersRequest {
45    int32 page = 1;
46    int32 per_page = 2;
47}
48message ListUsersResponse {
49    repeated User users = 1;
50}
51
52message CreateUserRequest {
53    string name = 1;
54    string email = 2;
55}
56
57message DeleteUserRequest {
58    string id = 1;
59}
60message Empty {}
Danger
With a single .proto file, both the gRPC endpoints for the backend and the REST endpoints for the frontend are generated automatically.

Implementing the gRPC Backend

For example, in GoLang (a popular implementation for gRPC):

go
 1// user_service.go
 2func (s *Server) GetUserStats(ctx context.Context, req *pb.StatsRequest) (*pb.StatsResponse, error) {
 3    stats, err := s.repo.FetchStats() // Fetch from Postgres, for example
 4    if err != nil {
 5        return nil, status.Errorf(codes.Internal, "FetchStats: %v", err)
 6    }
 7    return &pb.StatsResponse{
 8        ActiveUserCount: stats.Active,
 9        TotalUserCount:  stats.Total,
10    }, nil
11}

Setting up grpc-gateway

grpc-gateway reads the google.api.http annotations in the proto and generates an HTTP -> gRPC proxy converter.

For example, in a Go Mod project:

  1. Generate code from .proto:

    bash
    1protoc -I. --go_out=. --go-grpc_out=. --grpc-gateway_out=. user.proto
  2. Implement the gateway handler:

    go
    1mux := runtime.NewServeMux()
    2err := admin.RegisterUserServiceHandlerServer(ctx, mux, userServer)
    3if err != nil {
    4   log.Fatalf("Failed to register: %v", err)
    5}
    6http.ListenAndServe(":8080", mux)
Danger
grpc-gateway will expose /admin/users/stats, /admin/users, and so on as REST endpoints, while forwarding the requests to the gRPC handlers.

Simulating the Request Flow

For example, a React frontend fetching user statistics:

js
1fetch("/admin/users/stats")
2  .then(res => res.json())
3  .then(res => console.log(res));

On the backend:

  • HTTP GET /admin/users/stats
  • grpc-gateway converts it into the GetUserStats gRPC call
  • The GoLang handler runs the business logic
  • The result is returned to the frontend in JSON format

Flow Diagram (mermaid)

MERMAID
sequenceDiagram
  participant Frontend
  participant grpc-gateway
  participant UserService (gRPC)
  participant Database

  Frontend->>grpc-gateway: GET /admin/users/stats
  grpc-gateway->>UserService (gRPC): GetUserStats()
  UserService (gRPC)->>Database: SQL SELECT COUNT()
  Database-->>UserService (gRPC): Stats
  UserService (gRPC)-->>grpc-gateway: StatsResponse
  grpc-gateway-->>Frontend: JSON Stats

Benchmark: Efficiency

A brief analysis of a performance simulation:

Connection MethodRPS (req/sec)Median Latency (ms)
Legacy REST API950120
Native gRPC1,50040
grpc-gateway API1,40045

With grpc-gateway, we get performance almost on par with native gRPC, while keeping the flexibility of REST.


Testing and Observability

You can still write unit/integration tests against the gRPC handlers, and only need e2e tests at the grpc-gateway layer. grpc-gateway is mature and easily supports OpenAPI docs as well as logging middleware, ensuring observability.

go
1mux := runtime.NewServeMux(
2   runtime.WithForwardResponseOption(myLoggingResponseModifier),
3)

Comparison: REST vs grpc-gateway

FeatureREST-Onlygrpc-gateway
Strong typingWeakVery strong (proto)
Auto SDK generationUsually manualYes (from proto)
OpenAPI documentationSwaggerAutomatic from proto
PerformanceStandardClose to native gRPC
Migration to native gRPCDifficultVery easy

Notes and Best Practices

  1. Always start from the proto file: Treat the proto as the single source of truth for the API.
  2. Use the google.api.http annotations consistently so that REST endpoints are always available.
  3. Separate gateway handlers from backend logic—keep the REST handlers simple and put the heavy logic in the gRPC handlers.
  4. Version your proto and endpoints whenever there are major schema changes.
  5. Tracing and monitoring across layers is essential for debugging in production.

Conclusion

With grpc-gateway, the backend team can write modern, efficient, and future-proof APIs while still serving the common RESTful APIs needed by frontends, mobile apps, integrators, and other legacy clients. This admin dashboard case study showcases the power of the pattern: define once, use everywhere. For your next project, strongly consider starting from gRPC + grpc-gateway.


Want to try the sources?
gRPC-Gateway Documentation
Example code at github.com/your-repo/admin-dashboard-grpc-gateway

Thanks for reading!
Leave a comment if you would like an even deeper case study.

Related Articles

💬 Comments