Welcome to this gRPC learning project! This is a complete full-stack application designed to teach you gRPC from scratch. If you're completely new to gRPC, this README will guide you through everything you need to know.
gRPC (Google Remote Procedure Call) is a high-performance, open-source framework for building distributed systems. Think of it as a way for different applications to talk to each other, similar to REST APIs, but with some key advantages:
Feature | REST API | gRPC |
---|---|---|
Data Format | JSON (text) | Protocol Buffers (binary) |
Speed | Slower | Faster (binary data) |
Type Safety | No | Yes (strict schemas) |
Streaming | Limited | Built-in support |
HTTP Version | HTTP/1.1 | HTTP/2 |
- Protocol Buffers (.proto files): Define your API contract
- Services: Groups of related RPC methods
- Messages: Data structures sent between client and server
- Streaming: Real-time data flow support
This project demonstrates a pure gRPC architecture with no REST endpoints:
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β React App βββββββ β gRPC-Web βββββββ β gRPC Server β
β (Frontend) β β Server β β (Backend) β
β Port: 5173 β β Port: 8080 β β Port: 50051 β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β
β
βββββββββββββββββββ
β MySQL DB β
β Port: 3306 β
βββββββββββββββββββ
- Traditional gRPC Server (Port 50051): For server-to-server communication
- gRPC-Web Server (Port 8080): For browser clients (browsers can't directly connect to gRPC)
grpc-learning-project/
βββ backend/ # NestJS Backend
β βββ src/
β β βββ grpc/ # gRPC Implementation
β β β βββ auth.proto # API Contract Definition
β β β βββ grpc.service.ts # Traditional gRPC Server
β β β βββ grpc-web.service.ts # gRPC-Web Server
β β βββ auth/ # Authentication Logic
β β β βββ auth.service.ts # Business Logic
β β β βββ auth.module.ts # Auth Module
β β βββ entities/ # Database Models
β β β βββ user.entity.ts
β β βββ config/ # Database Configuration
β β βββ main.ts # Application Entry Point
β βββ package.json
β βββ .env # Environment Variables
βββ frontend/ # React Frontend
β βββ src/
β β βββ services/ # gRPC Client
β β β βββ grpc-client.ts
β β βββ components/ # React Components
β β β βββ Login.tsx
β β β βββ Dashboard.tsx
β β βββ grpc/ # Protocol Buffer Files
β β βββ auth.proto
β βββ package.json
β βββ .env # Environment Variables
βββ README.md # This file
- Node.js (v18 or higher)
- MySQL (running on port 3306)
- npm or yarn
# Start MySQL and create database
mysql -u root -p
CREATE DATABASE simple_app;
# Navigate to backend directory
cd backend
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Edit .env with your database credentials
# Start the backend (both gRPC servers)
npm run start:dev
You should see:
π Starting gRPC application...
β
gRPC application started successfully!
π‘ gRPC server running on port 50051
π gRPC-Web server running on port 8080
# Navigate to frontend directory (in new terminal)
cd frontend
# Install dependencies
npm install
# Start the frontend
npm run dev
Visit: http://localhost:5173
syntax = "proto3";
package auth;
service AuthService {
// Unary RPC (request-response)
rpc Login (LoginRequest) returns (LoginResponse);
rpc GetProfile (GetProfileRequest) returns (GetProfileResponse);
// Server-side streaming (server sends multiple messages)
rpc StreamNotifications (StreamNotificationsRequest) returns (stream NotificationMessage);
// Client-side streaming (client sends multiple messages)
rpc SendMessages (stream ClientMessage) returns (ClientMessagesResponse);
// Bidirectional streaming (both send multiple messages)
rpc ChatStream (stream ChatMessage) returns (stream ChatMessage);
}
message LoginRequest {
string username = 1;
string password = 2;
}
message LoginResponse {
string access_token = 1;
User user = 2;
}
message StreamNotificationsRequest {
string access_token = 1;
int32 duration_seconds = 2;
}
message NotificationMessage {
string id = 1;
string title = 2;
string message = 3;
string timestamp = 4;
string type = 5; // "info", "warning", "success", "error"
}
message ClientMessage {
string access_token = 1;
string message = 2;
string timestamp = 3;
}
message ChatMessage {
string access_token = 1;
string username = 2;
string message = 3;
string timestamp = 4;
string room = 5;
}
This file defines:
- Service:
AuthService
with 5 methods (2 unary + 3 streaming) - Messages: Data structures for requests and responses
- Streaming Types: Server-side, client-side, and bidirectional streaming
- Types: Strongly typed fields with numbers (for binary encoding)
Traditional gRPC Server (grpc.service.ts
):
// Implements the AuthService from auth.proto
@Injectable()
export class GrpcService {
// Unary RPC methods
async login(data: LoginRequest): Promise<LoginResponse> {
// Business logic here
}
// Server-side streaming - Server sends multiple messages
streamNotifications(call: any) {
// Send notifications every second
const interval = setInterval(() => {
call.write(notification);
}, 1000);
}
// Client-side streaming - Client sends multiple messages
sendMessages(call: any, callback: any) {
const messages = [];
call.on('data', (message) => {
messages.push(message);
});
call.on('end', () => {
callback(null, { total_messages: messages.length });
});
}
// Bidirectional streaming - Both send multiple messages
chatStream(call: any) {
call.on('data', (message) => {
call.write(echoResponse);
});
}
}
gRPC-Web Server (grpc-web.service.ts
):
// Bridges browser requests to gRPC
@Injectable()
export class GrpcWebService {
// Converts HTTP requests to gRPC calls
// Handles CORS and browser compatibility
// Uses Server-Sent Events for streaming
}
gRPC Client (grpc-client.ts
):
export class GrpcAuthClient {
// Unary RPC
async login(request: LoginRequest): Promise<LoginResponse> {
const response = await fetch(`${baseUrl}/auth.AuthService/Login`, {
method: 'POST',
headers: {
'Content-Type': 'application/grpc-web+json',
'X-Grpc-Web': '1',
},
body: JSON.stringify(request),
});
return response.json();
}
// Server-side streaming using async generators
async* streamNotifications(request: StreamNotificationsRequest) {
const response = await fetch(`${baseUrl}/auth.AuthService/StreamNotifications`, {
method: 'GET',
headers: { 'Accept': 'text/event-stream' },
});
for await (const notification of streamReader) {
yield notification;
}
}
// Client-side streaming
async sendMessages(messages: ClientMessage[]): Promise<ClientMessagesResponse> {
return await fetch(`${baseUrl}/auth.AuthService/SendMessages`, {
method: 'POST',
body: JSON.stringify({ messages }),
});
}
// Bidirectional streaming
async chatStream(message: ChatMessage): Promise<ChatMessage> {
return await fetch(`${baseUrl}/auth.AuthService/ChatStream`, {
method: 'POST',
body: JSON.stringify({ message }),
});
}
}
The application comes with a pre-created admin user:
- Username:
admin
- Password:
admin
- Open
http://localhost:5173
- Enter credentials
- Click "Login"
- You'll be redirected to the Dashboard
- Login to the dashboard
- Find the "Server-side Streaming" section
- Click "Start Notifications Stream"
- Watch 5 notifications appear automatically (one every second)
- Find the "Client-side Streaming" section
- Add multiple messages in the text boxes
- Click "Send Messages"
- See the summary of processed messages
- Find the "Bidirectional Streaming" section
- Type a message and click "Send"
- See your message and the server's echo response
- Continue chatting to see the conversation flow
Check the backend console to see gRPC calls in real-time:
π gRPC-Web Request: AuthService.Login { username: 'admin', password: 'admin' }
β
gRPC-Web Response: AuthService.Login { access_token: 'jwt_token_here', user: {...} }
π Server-side streaming started
π¨ Client-side streaming: Processing 3 messages
π¬ Bidirectional streaming: Echo response sent
- Run the application and see it work
- Examine the
.proto
file - This is your API contract - Look at the gRPC client - How frontend makes gRPC calls
- Check the backend services - How gRPC methods are implemented
- Add a new field to the User message in
auth.proto
- Update the frontend to display the new field
- Modify the backend to return the new field
- Test your changes
- Add streaming methods for real-time updates
- Implement error handling for gRPC calls
- Add authentication middleware for gRPC methods
- Create new services beyond authentication
npm run start:dev # Start in development mode
npm run build # Build for production
npm run start:prod # Start in production mode
npm run dev # Start development server
npm run build # Build for production
npm run preview # Preview production build
backend/src/grpc/auth.proto
- API contract definitionbackend/src/grpc/grpc-web.service.ts
- gRPC-Web server implementationfrontend/src/services/grpc-client.ts
- gRPC client implementationfrontend/src/components/Login.tsx
- How frontend uses gRPCbackend/src/auth/auth.service.ts
- Business logic
- REST: No guarantee that client and server agree on data structure
- gRPC: Compile-time checks ensure compatibility
- REST: JSON parsing overhead
- gRPC: Binary protocol buffers are faster
- REST: Request-response only
- gRPC: Built-in support for streaming data
- REST: Manual client code
- gRPC: Automatic client generation from .proto files
Solution: Ensure MySQL is running and environment variables are correct
Solution: Check if port 8080 is available and restart the backend
Solution: Verify the backend is running and accessible on port 8080
- Read the gRPC documentation: https://grpc.io/docs/
- Learn Protocol Buffers: https://developers.google.com/protocol-buffers
- Explore streaming: Add server-streaming or bidirectional streaming
- Add more services: Create new .proto files for different features
- Deploy to production: Learn about gRPC deployment strategies
This project teaches you:
- β How to define gRPC services with Protocol Buffers
- β How to implement gRPC servers in NestJS
- β How to create gRPC clients in React
- β How to handle authentication with gRPC
- β How to bridge gRPC to web browsers with gRPC-Web
- β
How to implement all 4 types of gRPC methods:
- Unary RPC: Simple request-response (Login, GetProfile)
- Server-side streaming: Server sends multiple messages (Notifications)
- Client-side streaming: Client sends multiple messages (Bulk messages)
- Bidirectional streaming: Both send multiple messages (Chat)
- β How to build a complete full-stack application without REST
- β How to handle real-time communication with gRPC streaming
Feel free to:
- Add new gRPC methods
- Improve error handling
- Add streaming examples
- Enhance documentation
- Create more complex examples
See CONTRIBUTING.md for detailed contribution guidelines.
![]() Anuj Patil Creator & Maintainer |
Happy gRPC Learning! π
If you have questions, examine the code, run the application, and experiment with making changes. The best way to learn gRPC is by doing!