Microservices

June 13, 2026 · View on GitHub

Use tRPC at the edge and delegate heavy domain operations to NestJS microservices via TCP, Redis, NATS, or other transports.

Architecture

┌─────────────────────────┐
│   tRPC Gateway (Nest)   │  ← public-facing, TrpcModule
│   @Router('orders')     │
│     @Query() get()      │──→ ClientProxy.send('orders.findById')
└─────────────────────────┘

     TCP / Redis / NATS

┌─────────────────────────┐
│   Orders Microservice   │  ← internal, @nestjs/microservices
│   @MessagePattern(...)  │
└─────────────────────────┘

Gateway Service

import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';

@Injectable()
export class OrdersGatewayService {
  constructor(@Inject('ORDERS_CLIENT') private readonly client: ClientProxy) {}

  async findById(id: string) {
    return lastValueFrom(this.client.send('orders.findById', { id }));
  }
}

Gateway Router

import { Input, Query, Router } from '@nest-native/trpc';

@Router('orders')
export class OrdersRouter {
  constructor(private readonly orders: OrdersGatewayService) {}

  @Query()
  get(@Input('id') id: string) {
    return this.orders.findById(id);
  }
}

Client Proxy Wiring

import { ClientProxyFactory, Transport } from '@nestjs/microservices';

@Module({
  providers: [
    {
      provide: 'ORDERS_CLIENT',
      useFactory: () =>
        ClientProxyFactory.create({
          transport: Transport.TCP,
          options: { host: '127.0.0.1', port: 4001 },
        }),
    },
    OrdersGatewayService,
    OrdersRouter,
  ],
})
export class OrdersModule {}

This keeps tRPC procedures thin while preserving Nest transport strategies for internal service boundaries.