# How to Implement Hybrid Microservices in NestJS: HTTP and TCP Together

> Learn how to implement hybrid microservices in NestJS combining HTTP and TCP. Start your NestJS app, connect a TCP microservice, and launch them together seamlessly.

- Repository: [nestjs/nest](https://github.com/nestjs/nest)
- Tags: how-to-guide
- Published: 2026-03-01

---

**Use `NestFactory.create()` to bootstrap your HTTP application, then call `app.connectMicroservice()` with `Transport.TCP` to attach a TCP listener, followed by `await app.startAllMicroservices()` before `await app.listen()`.**

The **nestjs/nest** repository provides native support for hybrid applications that serve HTTP requests and TCP microservice messages from the same process. This pattern allows REST controllers and message handlers to share providers, configuration, and modules while communicating over different transports. In `sample/03-microservices`, the framework demonstrates how to combine an HTTP server on port 3001 with a TCP microservice listener on port 3000 using a single bootstrap sequence.

## What Is a Hybrid NestJS Application?

A **hybrid application** runs multiple server transports within one NestJS context. The HTTP layer handles traditional REST requests through `@Controller` decorators, while the microservice layer processes `@MessagePattern` and `@EventPattern` calls over TCP sockets. Both sides access the same singleton providers and database connections because they exist within a single `NestApplicationContext`.

The architecture follows this sequence:
1. Create the HTTP application with `NestFactory.create(AppModule)`
2. Register one or more microservices via `app.connectMicroservice<MicroserviceOptions>()`
3. Initialize microservice listeners with `app.startAllMicroservices()`
4. Start the HTTP server with `app.listen(port)`

## Bootstrap a Hybrid HTTP and TCP Microservice

The entry point in [`sample/03-microservices/src/main.ts`](https://github.com/nestjs/nest/blob/main/sample/03-microservices/src/main.ts) demonstrates the complete bootstrap pattern for a hybrid deployment.

### Create the HTTP Application Foundation

Begin by creating the standard NestJS HTTP application. This establishes the root dependency injection container that the microservice will also use.

```typescript
// sample/03-microservices/src/main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // HTTP application is now ready for middleware and controllers
}

```

### Connect the TCP Microservice Transport

Attach a TCP microservice to the existing HTTP instance using `connectMicroservice()`. Pass `Transport.TCP` in the options object to specify the transport protocol.

```typescript
  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.TCP,
    options: {
      retryAttempts: 5,
      retryDelay: 3000,
    },
  });

```

The `options` object configures the TCP listener behavior. By default, the TCP transport binds to **localhost:3000**, while the HTTP server binds to the port specified in `app.listen()`.

### Start All Microservices Before the HTTP Server

You must start the microservice listeners before the HTTP server to ensure all transport layers are ready to accept connections.

```typescript
  await app.startAllMicroservices();
  await app.listen(3001);
  console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

```

The `startAllMicroservices()` method iterates over every microservice registered with `connectMicroservice()` and invokes their individual `listen()` methods. This guarantees that TCP sockets are bound before the HTTP server begins accepting requests.

## Handle Messages and Proxy HTTP Requests

The [`sample/03-microservices/src/app.controller.ts`](https://github.com/nestjs/nest/blob/main/sample/03-microservices/src/app.controller.ts) file demonstrates how to implement both sides of the hybrid architecture: message handlers for TCP clients and HTTP endpoints that delegate to those handlers.

### Define TCP Message Pattern Handlers

Use the `@MessagePattern()` decorator to define methods that respond to specific command patterns sent over TCP.

```typescript
// sample/03-microservices/src/app.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class AppController {
  @MessagePattern({ cmd: 'sum' })
  sum(data: number[]): number {
    return (data || []).reduce((a, b) => a + b);
  }

  @MessagePattern({ cmd: 'streaming' })
  streaming(data: number[]) {
    return from(data); // Returns an Observable stream
  }
}

```

These handlers execute whenever a TCP client sends a message matching the pattern object. The method receives the payload directly and can return either a value or an `Observable` for streaming responses.

### Create HTTP Endpoints That Delegate to Microservices

Inject a `ClientProxy` using the `@Client()` decorator to communicate from the HTTP controller back to the TCP microservice running in the same process.

```typescript
import { Body, Controller, HttpCode, Post, Query } from '@nestjs/common';
import { Client, ClientProxy, Transport } from '@nestjs/microservices';
import { Observable } from 'rxjs';
import * as fs from 'fs';
import * as path from 'path';

@Controller()
export class AppController {
  @Client({
    transport: Transport.TCP,
    options: {
      tlsOptions: {
        ca: [
          fs.readFileSync(
            path.join(__dirname, 'ca.cert.pem'),
            'utf-8',
          ).toString(),
        ],
      },
    },
  })
  client: ClientProxy;

  @Post()
  @HttpCode(200)
  call(
    @Query('command') cmd: string,
    @Body() data: number[],
  ): Observable<number> {
    return this.client.send<number>({ cmd }, data);
  }
}

```

The `client.send()` method returns an `Observable` that resolves when the TCP message handler completes. NestJS automatically subscribes to this observable and sends the result as the HTTP response body.

## Register Dynamic Client Proxies for Dependency Injection

For complex dependency injection scenarios, use `ClientsModule.registerAsync()` in your module configuration. The integration test file [`integration/microservices/src/tcp-tls/app.module.ts`](https://github.com/nestjs/nest/blob/main/integration/microservices/src/tcp-tls/app.module.ts) shows three registration patterns: factory-based, class-based, and custom proxy classes.

```typescript
// integration/microservices/src/tcp-tls/app.module.ts
import { Module, Injectable } from '@nestjs/common';
import {
  ClientsModule,
  ClientsModuleOptionsFactory,
  ClientOptions,
  Transport,
  ClientTCP,
} from '@nestjs/microservices';
import { ConfigService } from './config.service';

@Injectable()
class ClientOptionService implements ClientsModuleOptionsFactory {
  constructor(private readonly configService: ConfigService) {}
  
  createClientOptions(): ClientOptions {
    return {
      transport: this.configService.get('transport'),
      options: { tlsOptions: { ca: caCert } },
    };
  }
}

@Module({
  imports: [
    ClientsModule.registerAsync([
      {
        name: 'USE_FACTORY_CLIENT',
        useFactory: (cfg: ConfigService) => ({
          transport: cfg.get('transport'),
          options: { tlsOptions: { ca: caCert } },
        }),
        inject: [ConfigService],
        imports: [ConfigModule],
      },
      {
        name: 'USE_CLASS_CLIENT',
        useClass: ClientOptionService,
        imports: [ConfigModule],
      },
      {
        name: 'CUSTOM_PROXY_CLIENT',
        useFactory: () => ({
          customClass: class extends ClientTCP {
            serializeError(err) {
              return new RpcException(err);
            }
          },
        }),
      },
    ]),
  ],
})
export class ApplicationModule {}

```

Inject these dynamic clients into services using the `@Inject()` decorator with the registered name: `@Inject('USE_FACTORY_CLIENT') private client: ClientProxy`.

## Summary

- **Hybrid applications** combine HTTP servers and TCP microservices in a single process using `NestFactory.create()` followed by `app.connectMicroservice()`.
- **Bootstrap sequence** matters: always call `await app.startAllMicroservices()` before `await app.listen()` to ensure transport layers initialize correctly.
- **Shared context** allows both HTTP controllers and TCP message handlers to inject the same providers and database connections.
- **ClientProxy** enables HTTP endpoints to delegate work to TCP microservices via `client.send()` or `client.emit()`.
- **Advanced registration** via `ClientsModule.registerAsync()` supports factory patterns, configuration services, and custom client classes for TLS or error handling customization.

## Frequently Asked Questions

### What port does the TCP microservice listen on by default?

By default, the TCP transport binds to **localhost:3000**. You can override this by specifying the `host` and `port` properties in the `options` object passed to `connectMicroservice()`. The HTTP server port is configured separately in `app.listen()`.

### Can I connect multiple microservices to one HTTP application?

Yes. You can call `app.connectMicroservice()` multiple times with different transports or port configurations. Invoke `app.startAllMicroservices()` once to initialize all registered microservices simultaneously. Each microservice runs its own listener while sharing the same dependency injection container.

### How do I handle errors when proxying from HTTP to TCP?

Errors thrown in TCP message handlers propagate through the `ClientProxy` observable. Subscribe to the observable in your HTTP controller or use an exception filter. Alternatively, provide a **custom client class** via `ClientsModule.registerAsync()` that overrides `serializeError()` to transform errors into `RpcException` instances before they reach the HTTP layer.

### Is it possible to use TLS with TCP microservices in NestJS?

Yes. Pass `tlsOptions` within the transport options object when configuring either the server side (`connectMicroservice`) or the client side (`@Client` decorator or `ClientsModule`). Provide the certificate authority, key, and certificate files as shown in [`integration/microservices/src/tcp-tls/app.module.ts`](https://github.com/nestjs/nest/blob/main/integration/microservices/src/tcp-tls/app.module.ts) to enable encrypted TCP communication.