Part 3: Building gRPC Services with TypeScript and Node.js

From Zero to Production-Ready gRPC Service

In 2022, I built my first production gRPC service—an order processing system handling 50,000 requests per day. I made every rookie mistake possible: no proper error handling, synchronous database calls blocking the event loop, no connection pooling, and worst of all, no structured logging. Debugging production issues was a nightmare.

This part contains the complete, production-ready architecture I wish I had started with. Every pattern here comes from real-world experience maintaining gRPC services at scale.

Project Setup

Initial Structure

mkdir grpc-ecommerce
cd grpc-ecommerce
npm init -y

Dependencies

{
  "name": "grpc-ecommerce",
  "version": "1.0.0",
  "description": "Production-ready gRPC microservices",
  "main": "dist/server.js",
  "scripts": {
    "proto:generate": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=./src/generated --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true,useOptionals=messages ./protos/**/*.proto",
    "build": "npm run proto:generate && tsc",
    "dev": "npm run proto:generate && tsx watch src/server.ts",
    "start": "node dist/server.js",
    "lint": "eslint src --ext .ts",
    "format": "prettier --write \"src/**/*.ts\""
  },
  "dependencies": {
    "@grpc/grpc-js": "^1.9.0",
    "@grpc/proto-loader": "^0.7.10",
    "dotenv": "^16.3.1",
    "pg": "^8.11.3",
    "redis": "^4.6.10",
    "winston": "^3.11.0",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@types/pg": "^8.10.0",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "eslint": "^8.50.0",
    "prettier": "^3.0.0",
    "ts-proto": "^1.164.0",
    "tsx": "^4.0.0",
    "typescript": "^5.2.0"
  }
}

TypeScript Configuration

Project Directory Structure

Protocol Buffer Definitions

Common Types

Order Service Proto

Product Service Proto

Generate TypeScript Code

This generates type-safe TypeScript interfaces in src/generated/.

Database Configuration

PostgreSQL Setup

Redis Configuration

Logger Configuration

Repository Layer

Order Repository

Product Repository

Service Layer

Order Service

gRPC Handler

gRPC Server

Main Server Entry

Key Takeaways

  1. Layered Architecture: Separate concerns (Repository → Service → Handler)

  2. Connection Pooling: Critical for database and Redis performance

  3. Caching Strategy: Use Redis for idempotency and frequently accessed data

  4. Error Handling: Always use try-catch and return proper gRPC status codes

  5. Logging: Structured logging for production debugging

  6. Graceful Shutdown: Clean up resources properly


Next: Part 4: Authentication and Authorization in gRPC

Series Navigation: gRPC 101 Series

Last updated