npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pirumu/nest-udp

v1.1.0

Published

A NestJS microservice transport layer for UDP communication

Downloads

83

Readme

Features

  • Full NestJS Integration - Seamless microservices architecture support
  • UDP Client & Server - Complete implementation for both sides using Node.js dgram module
  • Dual Pattern Support - Message patterns (request-response) and event patterns (fire-and-forget)
  • Improved UDP Reliability - REQ/ACK/RES pattern with automatic retries and chunk reassembly
  • Compression Support - Built-in gzip, optional snappy, lz4, zstd compression
  • Large Payload Handling - Automatic chunking and reassembly for messages exceeding MTU
  • Highly Customizable - Flexible socket options and custom implementations
  • TypeScript First - Full type safety and IntelliSense support

Requirements

  • Node.js: v20.0.0 or higher
  • NestJS: v11.0.0 or higher

Installation

npm install @pirumu/nest-udp
yarn add @pirumu/nest-udp
pnpm add @pirumu/nest-udp

Quick Start

1. Server Setup

Create a UDP microservice server using Node.js dgram:

import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions } from '@nestjs/microservices';
import { ServerUdp } from '@pirumu/nest-udp';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      strategy: new ServerUdp({
        host: '0.0.0.0',
        port: 41234,
        transport: 'udp4',
      }),
    },
  );

  await app.listen();
}
bootstrap();

2. Define Controllers

import { Controller } from '@nestjs/common';
import { MessagePattern, EventPattern, Payload, Ctx } from '@nestjs/microservices';
import { UdpContext } from '@pirumu/nest-udp';

@Controller()
export class AppController {
  // Request-Response pattern
  @MessagePattern('calculate')
  calculate(@Payload() data: { a: number; b: number }) {
    return { result: data.a + data.b };
  }

  // Fire-and-forget pattern
  @EventPattern('user.created')
  handleUserCreated(@Payload() user: any, @Ctx() context: UdpContext) {
    console.log('New user:', user);
  }
}

3. Client Setup

Register the UDP client in your module:

import { Module } from '@nestjs/common';
import { ClientsModule } from '@nestjs/microservices';
import { ClientUdp } from '@pirumu/nest-udp';

@Module({
  imports: [
    ClientsModule.register({
      clients: [
        {
          name: 'UDP_SERVICE',
          customClass: ClientUdp,
          options: {
            host: 'localhost',
            port: 41234,
            transport: 'udp4',
          },
        },
      ],
    }),
  ],
})
export class AppModule {}

4. Use the Client

import { Injectable, Inject } from '@nestjs/common';
import { ClientUdp } from '@pirumu/nest-udp';
import { lastValueFrom } from 'rxjs';

@Injectable()
export class AppService {
  constructor(
    @Inject('UDP_SERVICE') private readonly client: ClientUdp
  ) {}

  async calculate(a: number, b: number) {
    // Request-response (waits for reply)
    return lastValueFrom(
      this.client.send('calculate', { a, b })
    );
  }

  notifyUserCreated(user: any) {
    // Fire-and-forget (no reply expected)
    this.client.emit('user.created', user).subscribe();
  }
}

API Reference

ServerUdp Options

Built on top of Node.js dgram module (available since Node.js v20).

| Property | Type | Default | Description | |----------|------|---------|-------------| | host | string | '0.0.0.0' | Server bind address | | port | number | 3000 | Server listening port | | transport | 'udp4' \| 'udp6' | 'udp4' | UDP protocol version | | socketClass | Type<UdpSocket> | JsonUdpSocket | Socket implementation (JsonUdpSocket, ReliableUdpSocket, or custom) | | socketOptions | dgram.SocketOptions | {} | Node.js dgram socket options | | bindOptions | dgram.BindOptions | {} | Node.js dgram bind options | | reliableOptions | ReliableUdpSocketOptions | - | ReliableUdpSocket configuration (when using ReliableUdpSocket) |

ClientUdp Options

| Property | Type | Default | Description | |----------|------|---------|-------------| | host | string | 'localhost' | Target server address | | port | number | 3000 | Target server port | | type | 'udp4' \| 'udp6' | 'udp4' | UDP protocol version | | socketClass | Type<UdpSocket> | JsonUdpSocket | Socket implementation (JsonUdpSocket, ReliableUdpSocket, or custom) | | socketOptions | dgram.SocketOptions | {} | Node.js dgram socket options | | bindOptions | dgram.BindOptions | {} | Node.js dgram bind options | | reliableOptions | ReliableUdpSocketOptions | - | ReliableUdpSocket configuration (when using ReliableUdpSocket) |

ReliableUdpSocketOptions

Configuration for ReliableUdpSocket. Used when socketClass: ReliableUdpSocket.

| Property | Type | Default | Description | |----------|------|---------|-------------| | maxMessageSize | number | 1400 | Maximum message size before chunking | | maxRetries | number | 3 | Maximum retry attempts per message/chunk | | retryInterval | number | 100 | Milliseconds between retry attempts | | enableChecksum | boolean | true | Enable SHA-256 checksum validation | | requestTimeout | number | 5000 | Request timeout in milliseconds | | chunkSize | number | 1200 | Size of each chunk in bytes | | reassemblyTimeout | number | 30000 | Timeout for chunk reassembly | | compression | CompressionConfig | - | Compression configuration | | messageIdOptions | object | - | Snowflake ID generator options |

CompressionConfig

Compression configuration for ReliableUdpSocket.

| Property | Type | Default | Description | |----------|------|---------|-------------| | enabled | boolean | false | Enable compression | | codec | CompressionCodecType | GZIP | Compression codec to use | | level | number | 6 | Compression level (codec-specific) | | minSize | number | 256 | Minimum size in bytes to compress | | minReduction | number | 10 | Minimum reduction percentage to use compression |

Available Compression Codecs:

Built-in:

  • CompressionCodecType.NONE - No compression
  • CompressionCodecType.GZIP - Built-in gzip compression

Requires npm packages:

  • CompressionCodecType.SNAPPY - Fast, moderate compression (needs snappy)
  • CompressionCodecType.LZ4 - Very fast, moderate compression (needs lz4)
  • CompressionCodecType.ZSTD - Best compression, fast (needs @mongodb-js/zstd)
pnpm add snappy lz4 @mongodb-js/zstd

Socket Implementations

[!WARNING] UDP Protocol Limitations

UDP is inherently unreliable and has strict payload size limits:

  • Theoretical maximum: 65,507 bytes
  • Practical safe limit: ~1,400 bytes (network MTU dependent)

Payloads exceeding MTU get fragmented. If ANY fragment is lost, the ENTIRE message is lost silently.

Common symptoms:

  • Requests hang with no response
  • Intermittent failures (works sometimes, fails other times)
  • Works on localhost but fails over network

[!IMPORTANT] When to Use TCP Instead

Use NestJS TCP transport if you need:

  • Large messages
  • 100% guaranteed message delivery
  • Connection-oriented communication

JsonUdpSocket (Default)

The default socket implementation uses JSON serialization. Suitable for small messages (< 1.4KB) with basic UDP reliability.

ReliableUdpSocket

Provides improved reliability through REQ/ACK/RES pattern with automatic retries, chunking, and compression.

[!NOTE] ReliableUdpSocket improves UDP reliability but cannot make UDP 100% reliable. Packets can still be lost, duplicated, or arrive out of order due to UDP protocol limitations.

Configuration

import { ReliableUdpSocket, CompressionCodecType } from '@pirumu/nest-udp';

// Server
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  AppModule,
  {
    strategy: new ServerUdp({
      host: '0.0.0.0',
      port: 41235,
      type: 'udp4',
      socketClass: ReliableUdpSocket,
      reliableOptions: {
        // Message and retry configuration
        maxMessageSize: 1400,
        maxRetries: 3,
        retryInterval: 100,
        enableChecksum: true,

        // Compression configuration
        compression: {
          enabled: true,
          codec: CompressionCodecType.GZIP,
          level: 6,
          minSize: 256,
          minReduction: 10,
        },

        // Chunking configuration
        chunkSize: 1200,
        reassemblyTimeout: 30000,

        // Request tracking
        requestTimeout: 5000,
      },
    }),
  },
);

// Client
ClientsModule.register([{
  name: 'UDP_SERVICE',
  customClass: ClientUdp,
  options: {
    host: 'localhost',
    port: 41235,
    type: 'udp4',
    socketClass: ReliableUdpSocket,
    reliableOptions: {
      maxMessageSize: 1400,
      maxRetries: 3,
      retryInterval: 100,
      enableChecksum: true,

      compression: {
        enabled: true,
        codec: CompressionCodecType.GZIP,
        level: 6,
        minSize: 256,
        minReduction: 10,
      },

      chunkSize: 1200,
      reassemblyTimeout: 30000,
      requestTimeout: 5000,
    },
  },
}])

See ReliableUdpSocketOptions in API Reference for all configuration options.

Features

Improved Reliability:

  • REQ/ACK/RES pattern improves delivery success rate
  • Automatic retries with configurable attempts and intervals
  • SHA-256 checksum validation for data integrity
  • Request tracking with timeout handling

Large Payloads:

  • Automatic chunking for messages exceeding maxMessageSize
  • Each chunk uses REQ/ACK pattern for improved delivery
  • Automatic reassembly with timeout protection
  • Base64 encoding for binary-safe chunk transmission

Compression:

  • Multiple codec support (gzip, snappy, lz4, zstd)
  • Smart compression (only if size reduction meets threshold)
  • Configurable compression level and minimum size
  • Transparent compression/decompression
  • Reduces message size by 60-90% for typical JSON data

Performance:

  • Snowflake ID generation for unique message IDs
  • Efficient bit-packed message envelopes
  • Configurable buffer sizes for high-throughput scenarios

[!TIP] Examples

  • examples/reliable-server.ts - Complete server example
  • examples/reliable-client.ts - Complete client example

Advanced Usage

Error Handling with RxJS

Leverage RxJS operators for robust error handling:

import { catchError, retry, timeout } from 'rxjs/operators';
import { of } from 'rxjs';

client.send('unreliable-service', { data: 'test' })
  .pipe(
    timeout(5000),
    retry(3),
    catchError(error => {
      console.error('Request failed:', error);
      return of({ error: 'Service unavailable' });
    })
  )
  .subscribe(result => console.log(result));

Working with Context

Access UDP-specific context information including dgram RemoteInfo:

@MessagePattern('echo')
handleEcho(@Payload() data: any, @Ctx() context: UdpContext) {
  const remoteInfo = context.getRemoteInfo();
  console.log(`From: ${remoteInfo.address}:${remoteInfo.port}`);
  console.log(`Family: ${remoteInfo.family}`);
  console.log(`Size: ${remoteInfo.size} bytes`);
  return data;
}

Native dgram Socket Access

Access the underlying dgram socket for advanced use cases:

import * as dgram from 'node:dgram';

@Injectable()
export class AppService {
  constructor(
    @Inject('UDP_SERVICE') private readonly client: ClientUdp
  ) {}

  async onModuleInit() {
    await this.client.connect();
    
    // Access native dgram socket
    const socket = this.client.unwrap<dgram.Socket>();
    
    // Use native dgram APIs
    socket.setMulticastTTL(128);
    socket.setBroadcast(true);
  }
}

Custom Socket Class

Implement your own socket class for custom serialization:

import { UdpSocket } from '@pirumu/nest-udp';
import * as dgram from 'node:dgram';

class MsgPackUdpSocket extends UdpSocket {
  protected handleSend(message: any, host?: string, port?: number, callback?: (err?: any) => void): void {
    const buffer = msgpack.encode(message);
    this.socket.send(buffer, port!, host!, callback);
  }

  protected handleData(data: Buffer, rinfo: dgram.RemoteInfo): void {
    const message = msgpack.decode(data);
    this.socket.emit('data', message, rinfo);
  }
}

// Use in configuration
ClientsModule.register({
  clients: [{
    name: 'UDP_SERVICE',
    customClass: ClientUdp,
    options: {
      socketClass: MsgPackUdpSocket,
      // ... other options
    },
  }],
})

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is MIT licensed.

Support