install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/nestjs-microservices" ~/.claude/skills/intense-visions-harness-engineering-nestjs-microservices && rm -rf "$T"
manifest:
agents/skills/claude-code/nestjs-microservices/SKILL.mdsource content
NestJS Microservices
Connect services with ClientsModule, @MessagePattern, @EventPattern, and TCP/Redis transport
When to Use
- You are decomposing a monolith into independent services that communicate over a message broker
- You need request/response messaging between services (command-reply pattern)
- You need one-way event broadcasting to multiple downstream services
- You need to choose a transport (TCP for low-latency internal, Redis/RabbitMQ for durability)
Instructions
- Bootstrap as a microservice:
// main.ts const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, { transport: Transport.REDIS, options: { host: 'localhost', port: 6379 }, }); await app.listen();
- Handle incoming messages:
@Controller() export class OrdersController { @MessagePattern({ cmd: 'get_order' }) // request/response getOrder(@Payload() data: { id: string }): Promise<Order> { return this.ordersService.findOne(data.id); } @EventPattern('order_created') // fire-and-forget async handleOrderCreated(@Payload() data: OrderCreatedEvent): Promise<void> { await this.inventoryService.reserve(data.items); } }
- Call a microservice from another service:
// register the client in a module @Module({ imports: [ ClientsModule.register([ { name: 'ORDERS_SERVICE', transport: Transport.REDIS, options: { host: 'localhost', port: 6379 }, }, ]), ], }) // inject and use @Injectable() export class ApiGatewayService { constructor(@InjectClient('ORDERS_SERVICE') private client: ClientProxy) {} getOrder(id: string): Observable<Order> { return this.client.send<Order>({ cmd: 'get_order' }, { id }); } notifyOrderCreated(event: OrderCreatedEvent): Observable<void> { return this.client.emit('order_created', event); } }
- Hybrid application (HTTP + microservice on the same app):
const app = await NestFactory.create(AppModule); app.connectMicroservice<MicroserviceOptions>({ transport: Transport.REDIS, options: { host: 'localhost', port: 6379 }, }); await app.startAllMicroservices(); await app.listen(3000);
- Exception handling: Throw
inside message handlers — it serializes cleanly to the caller.RpcException
Details
Transport comparison:
- TCP — built-in, no external dependency, lowest latency, point-to-point only
- Redis — pub/sub with persistence off by default, good for event fan-out, requires Redis
- RabbitMQ — durable queues, dead-letter exchange, complex routing, good for reliable delivery
- Kafka — partitioned log, replay, high throughput, best for event sourcing and stream processing
- NATS — lightweight, fast, at-most-once delivery by default (NATS JetStream for persistence)
vs send()
: emit()
send() is request/response — it returns an Observable that emits the reply. emit() is fire-and-forget — it returns an Observable that completes when the message is sent (no reply). Always subscribe() to both, or convert to Promise with firstValueFrom().
and @Payload()
: Use @Ctx()
@Payload() to extract the message payload. Use @Ctx() to get the transport context (e.g., RmqContext for RabbitMQ to manually acknowledge messages).
Manual acknowledgment (RabbitMQ):
@MessagePattern('order_created') async handle(@Payload() data: OrderCreatedEvent, @Ctx() context: RmqContext) { const channel = context.getChannelRef(); const message = context.getMessage(); await this.processOrder(data); channel.ack(message); // only ack after successful processing }
Serialization: By default, NestJS serializes/deserializes with
JSON.stringify/parse. For binary protocols (protobuf, msgpack), configure a custom serializer/deserializer pair.
Source
https://docs.nestjs.com/microservices/basics
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.