A high-performance gRPC-based API for a school management system that administrative staff can use to manage students, teachers, and executive staff members. Built with Go, Protocol Buffers, and MongoDB, this system provides a robust, type-safe, and efficient alternative to traditional REST APIs.
- Key Features
- Technology Stack
- Architecture
- API Services
- Message Types
- Security Features
- Setup and Installation
- Running the Server
- Testing
- Best Practices
- Common Pitfalls
- ✅ CRUD operations for students, teachers, and executives
- ✅ Bulk operations support (add, update, delete multiple records)
- ✅ Advanced filtering and sorting capabilities
- ✅ Pagination support for large datasets
- ✅ Class-based student grouping with class teacher management
- ✅ JWT-based authentication
- ✅ Login/Logout functionality
- ✅ Password management (update, reset, forgot password)
- ✅ User deactivation capabilities
- ✅ Token-based session management
- ✅ Request interceptors for authentication
- ✅ Rate limiting (configurable per IP)
- ✅ Response time tracking
- ✅ Input validation using Protocol Buffer validation rules
- ✅ TLS/SSL support (configurable)
- Language: Go 1.25.0
- RPC Framework: gRPC (google.golang.org/grpc v1.75.1)
- Protocol: Protocol Buffers v3 (proto3)
- Database: MongoDB (go.mongodb.org/mongo-driver v1.17.4)
- Authentication: JWT (github.com/golang-jwt/jwt/v5 v5.3.0)
- Password Hashing: bcrypt (golang.org/x/crypto v0.39.0)
- Validation: protoc-gen-validate v1.2.1
- Configuration: godotenv v1.5.1
go-gRPC-api-school-mgmt/
├── cmd/grpcapi/ # Main server entry point
├── internals/
│ ├── api/
│ │ ├── handlers/ # gRPC service implementations
│ │ └── interceptors/ # Middleware (auth, rate limiting, logging)
│ ├── models/ # Data models
│ └── repositories/ # Database operations (MongoDB)
├── pkg/utils/ # Utility functions (JWT, password, error handling)
├── proto/ # Protocol Buffer definitions
│ ├── gen/ # Generated Go code from .proto files
│ └── validate/ # Validation rules
├── cert/ # TLS certificates
└── data/ # Sample/seed data
The server implements a chain of interceptors for cross-cutting concerns:
- Response Time Interceptor - Tracks and logs request duration
- Authentication Interceptor - Validates JWT tokens (except for public endpoints)
- Rate Limiting Interceptor - Controls request rate per IP (optional)
The ExecsService manages administrative staff with full authentication capabilities.
| Method | Description | Auth Required |
|---|---|---|
GetExecs |
Retrieve executives with optional filtering and sorting | Yes |
AddExecs |
Add one or more executives | Yes |
UpdateExecs |
Update one or more executives | Yes |
DeleteExecs |
Delete executives by IDs | Yes |
Login |
Authenticate and receive JWT token | No |
Logout |
Invalidate current session token | Yes |
UpdatePassword |
Change password for authenticated user | Yes |
ResetPassword |
Reset password using reset code | No |
ForgotPassword |
Request password reset email | No |
DeactivateUser |
Deactivate user accounts | Yes |
Login
message ExecLoginRequest {
string username = 1; // min 6 chars, alphanumeric + @.#$+-
string password = 2; // min 9 chars, alphanumeric + @.#$+-
}
message ExecLoginResponse {
bool status = 1;
string token = 2; // JWT token
}Get Executives
message GetExecsRequest {
Exec exec = 1; // Filter criteria
repeated SortField sort_by = 2; // Sorting options
}Exec Model
message Exec {
string id = 1;
string first_name = 2; // Letters and spaces only
string last_name = 3; // Letters and spaces only
string email = 4; // Valid email format
string username = 5; // Min 6 chars
string password = 6; // Min 9 chars (hashed in DB)
string password_changed_at = 7;
string user_created_at = 8;
string password_reset_token = 9;
string password_token_expires = 10;
string role = 11;
bool inactive_status = 12;
}The StudentsService handles student records with pagination support.
| Method | Description | Auth Required |
|---|---|---|
GetStudents |
Retrieve students with filtering, sorting, and pagination | Yes |
AddStudents |
Add one or more students | Yes |
UpdateStudents |
Update one or more students | Yes |
DeleteStudents |
Delete students by IDs | Yes |
Get Students
message GetStudentsRequest {
Student student = 1; // Filter criteria
repeated SortField sort_by = 2; // Sorting options
uint32 page_number = 3; // Pagination
uint32 page_size = 4; // Results per page
}Student Model
message Student {
string id = 1;
string first_name = 2;
string last_name = 3;
string email = 4;
string class = 5; // e.g., "10th A", "12th B"
}Delete Response
message DeleteStudentsConfirmation {
string status = 1;
repeated string deleted_ids = 2; // IDs of deleted students
}The TeachersService manages teacher records and their class assignments.
| Method | Description | Auth Required |
|---|---|---|
GetTeachers |
Retrieve teachers with filtering and sorting | Yes |
AddTeachers |
Add one or more teachers | Yes |
UpdateTeachers |
Update one or more teachers | Yes |
DeleteTeachers |
Delete teachers by IDs (MongoDB ObjectID format) | Yes |
GetStudentsByClassTeacher |
Get all students assigned to a specific teacher | Yes |
GetStudentCountByClassTeacher |
Get count of students for a class teacher | Yes |
Teacher Model
message Teacher {
string id = 1;
string first_name = 2; // Letters and spaces only
string last_name = 3; // Letters and spaces only
string email = 4; // Valid email format
string class = 5; // Alphanumeric and spaces
string subject = 6; // Alphanumeric and spaces
}Get Students by Class Teacher
message TeacherId {
string id = 1; // Must be 24-char hex (MongoDB ObjectID)
}
// Returns: Students (list of students)Get Student Count
message StudentCount {
bool status = 1;
int32 student_count = 2;
}Sort Field
message SortField {
string field = 1; // Field name to sort by
Order order = 2; // ASC or DESC
}
enum Order {
ASC = 0;
DESC = 1;
}The API uses protoc-gen-validate for automatic input validation:
- Email validation: Ensures proper email format
- String patterns: Regex validation for names, usernames, passwords
- Length constraints: Minimum/maximum string lengths
- MongoDB ObjectID validation: 24-character hex string pattern
- Required fields: Enforced at the protocol level
Examples:
// Email must be valid
string email = 4 [(validate.rules).string = {email: true}];
// MongoDB ObjectID (24 hex chars)
string id = 1 [(validate.rules).string = {
min_len: 24,
max_len: 24,
pattern: "^[a-fA-F0-9]{24}$"
}];
// Name (letters and spaces only)
string first_name = 2 [(validate.rules).string = {
pattern: "^[A-Za-z ]*$"
}];- Token Generation: On successful login
- Token Validation: Via authentication interceptor
- Token Storage: In-memory store with automatic cleanup
- Token Invalidation: On logout
- Header Format:
Authorization: Bearer <token>
- Hashing: bcrypt algorithm
- Minimum Length: 9 characters
- Character Requirements: Alphanumeric + special chars (@.#$+-)
- Reset Mechanism: Token-based with expiration
- Update Protection: Requires current password
- Implementation: Per-IP rate limiting
- Configurable: Requests per time window
- Reset Mechanism: Automatic visitor count reset
- Example: 50 requests per minute (configurable)
The following endpoints bypass authentication:
/main.ExecsService/Login/main.ExecsService/ForgotPassword/main.ExecsService/ResetPassword
- Certificate and key files in
cert/directory - Configurable via environment variables
- Can be enabled/disabled based on deployment needs
- Go 1.25.0 or higher
- MongoDB (local or cloud instance)
- Protocol Buffer compiler (
protoc) - Go protobuf plugins
-
Clone the repository
git clone https://github.com/aayushxrj/go-gRPC-api-school-mgmt.git cd go-gRPC-api-school-mgmt -
Install dependencies
go mod download
-
Set up environment variables Create a
.envfile incmd/grpcapi/:SERVER_PORT=50051 MONGODB_URI=mongodb://localhost:27017 DB_NAME=school_management JWT_SECRET=your-secret-key-here CERT_FILE=../../cert/cert.pem KEY_FILE=../../cert/key.pem
-
Generate Protocol Buffer code (if modified)
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ --validate_out="lang=go:." --validate_opt=paths=source_relative \ proto/*.proto -
Seed the database (optional)
# Import sample data from data/ directory mongoimport --db school_management --collection students --file data/students_data.json mongoimport --db school_management --collection teachers --file data/teachers_data.json mongoimport --db school_management --collection execs --file data/execs_data.json
cd cmd/grpcapi
go run server.go# Build binary
go build -o bin/server cmd/grpcapi/server.go
# Run with TLS enabled
./bin/serverdocker build -t school-mgmt-grpc .
docker run -p 50051:50051 school-mgmt-grpcThe server will start on the port specified in .env (default: 50051).
The server has gRPC reflection enabled, allowing tools like grpcurl and grpcui:
# List all services
grpcurl -plaintext localhost:50051 list
# List methods for a service
grpcurl -plaintext localhost:50051 list main.StudentsService
# Call a method
grpcurl -plaintext -d '{"username": "admin", "password": "password123"}' \
localhost:50051 main.ExecsService/LoginPostman supports gRPC natively:
- Create new gRPC request
- Enter server URL:
localhost:50051 - Import proto files or use server reflection
- Select service and method
- Fill in request message
- Add metadata for auth:
authorization: Bearer <token>
# Install ghz
go install github.com/bojand/ghz/cmd/ghz@latest
# Run benchmark (example config in ghz_config.json)
ghz --config ghz_config.json# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run specific package tests
go test ./internals/api/handlers/- Separation of Concerns: Handlers, interceptors, repositories, and models are in separate packages
- Reusable Components: Utility functions centralized in
pkg/utils/ - Interface-based Design: Allows for easy mocking and testing
- Proto Comments: Document all services, methods, and messages in
.protofiles - Code Comments: Explain complex business logic
- API Documentation: Auto-generated from proto files
- gRPC Status Codes: Use appropriate codes (e.g.,
codes.InvalidArgument,codes.Unauthenticated) - Error Messages: Descriptive and user-friendly
- Structured Errors: Consistent error response format
- Centralized Handler: Error handling utilities in
pkg/utils/error_handler.go
- Input Validation: Enforced at protocol level using validation rules
- Password Hashing: Always hash passwords before storage
- JWT Expiration: Implement token expiration and refresh mechanisms
- HTTPS/TLS: Use in production environments
- Environment Variables: Never commit secrets to version control
- Unit Tests: Test individual handlers and utilities
- Integration Tests: Test end-to-end flows
- Mocking: Mock database and external dependencies
- Benchmarking: Use tools like
ghzfor performance testing
- Connection Pooling: Reuse MongoDB connections
- Indexing: Create indexes on frequently queried fields
- Transactions: Use MongoDB transactions for multi-document operations
- Error Recovery: Graceful handling of connection failures
- Interceptor Chain: Minimize overhead in interceptors
- Database Queries: Optimize with proper indexing and projection
- Pagination: Always paginate large result sets
- Connection Reuse: Keep database connections alive
- ❌ Don't create too many RPC methods for simple operations
- ✅ Use flexible filter/query patterns instead
- ✅ Leverage protobuf's optional fields for partial updates
- ❌ Don't skip authentication for "internal" endpoints
- ❌ Don't store passwords in plain text
- ❌ Don't expose sensitive data in error messages
- ✅ Always validate and sanitize inputs
- ✅ Use TLS in production
- ✅ Implement proper RBAC (Role-Based Access Control)
- ❌ Don't leave proto files undocumented
- ❌ Don't ignore the importance of examples
- ✅ Document request/response formats
- ✅ Provide usage examples
- ✅ Keep README updated
- ❌ Don't skip unit tests for "simple" handlers
- ❌ Don't forget edge cases
- ✅ Test authentication flows thoroughly
- ✅ Test error scenarios
- ✅ Perform load testing before production
- ❌ Don't fetch all records without pagination
- ❌ Don't perform N+1 queries
- ✅ Use MongoDB aggregation pipelines for complex queries
- ✅ Implement proper indexing strategy
- ✅ Monitor and optimize slow queries
- ❌ Don't ignore race conditions
- ❌ Don't use global state without proper synchronization
- ✅ Use mutexes or channels for shared state (see rate limiter)
- ✅ Design for stateless operations where possible
- ❌ Don't deploy without logging
- ❌ Don't ignore performance metrics
- ✅ Log important operations and errors
- ✅ Track response times (already implemented)
- ✅ Monitor server health and resource usage
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Go best practices and idioms
- Write unit tests for new features
- Update proto files before implementation
- Document all public APIs
- Run
go fmtandgo vetbefore committing
This project is licensed under the MIT License - see the LICENSE file for details.