A microservices messaging framework for NestJS 11+ with multi-transport support (NATS, Kafka, HTTP/SSE, HTTP/2, WebSocket, Socket.IO), designed for building scalable distributed systems with type-safe inter-service communication.
Full documentation lives in docs/. This README only covers a minimal NATS setup. For every other feature — Kafka, HTTP/2, the saga orchestrator, outbox, sliding-window circuit breakers, idempotency, JWT, OpenTelemetry, the DevTools dashboard, and a hundred more — start at the docs index.
- 🚀 Type-safe messaging across NATS, Kafka, HTTP/SSE, HTTP/2, WebSocket, Socket.IO
- 🔄 Query (request/response), emit (fire-and-forget), publish/subscribe, broadcast, streaming
- 🎯 Declarative routing via
@Signaldecorator with method versioning - 🧱 Pluggable codecs — MessagePack default, JSON, fast-json-stringify
- 🪶 Compression (gzip, deflate, zstd) with worker-thread offload
- 🧯 Resilience: retry with jitter, sliding-window circuit breaker, hedging, adaptive concurrency, idempotency cache (LRU + Redis distributed store), replay protection, rate limiting (in-process and Redis-cluster) — usable as
@Hedge/@CircuitBreaker/@Adaptive/@Backpressuredecorators - 🧰 Reliable patterns: transactional outbox, effectively-once inbox (with a transactional store — e.g.
PgInboxStore), saga with compensation, CQRS bridge, event store — in-memory + SQLite + Postgres production stores - 🧪 In-memory transport (
createMemoryTransport()) +MemoryHarnessfor unit tests with no broker dependency - 📈 Observability: pino, Prometheus metrics, OpenTelemetry, structured DLQ
- 🪟 DevTools UI — live Next.js 16 dashboard with circuits/methods/errors/trace/replay
- 🔐 Security: ACL, JWT/JWKS, mTLS, PII redaction
- 🩺 Liveness + readiness probes with pluggable checks (pg/redis/nats/kafka/http)
- 🌐 Service discovery — built-in heartbeat + pluggable Consul / Kubernetes DNS providers
- 🛡️ Graceful shutdown, BigInt support, did-you-mean suggestions
See CHANGELOG.md for version history.
- Node.js ≥ 24 (tested on 26) — enforced by the package's
enginesfield, so older runtimes are refused at install time. The built-innode:sqlitestore and several runtime APIs require Node 24. - TypeScript ≥ 6
- NestJS ≥ 11
npm install @riaskov/nevo-messaging
npm install @nestjs/common @nestjs/core @nestjs/microservices @nestjs/config @nestjs/platform-fastify rxjs reflect-metadata
npm install @nats-io/transport-node @nats-io/nats-core # for NATS — install only the transport(s) you usenpx nevo-gen user --transport nats --port 8086
cd user
npm install
npm run devSee docs/service-scaffolding.md.
A complete NATS-backed microservice is four small files.
// user.service.ts
import { Injectable, Inject } from "@nestjs/common"
import { NatsClientBase, NevoNatsClient } from "@riaskov/nevo-messaging"
@Injectable()
export class UserService extends NatsClientBase {
constructor(@Inject("NEVO_NATS_CLIENT") client: NevoNatsClient) {
super(client)
}
async getById(id: bigint) {
return { id, name: "John Doe", email: "john@example.com" }
}
async create(input: { name: string; email: string }) {
return { id: 123n, ...input }
}
}// user.controller.ts
import { Controller, Inject } from "@nestjs/common"
import { NatsSignalRouter, Signal } from "@riaskov/nevo-messaging"
import { UserService } from "./user.service"
@Controller()
@NatsSignalRouter([UserService])
export class UserController {
constructor(@Inject(UserService) private readonly users: UserService) {}
@Signal("user.getById", "getById", (d: any) => [d.id])
getById() {}
@Signal("user.create", "create", (d: any) => [d])
create() {}
}// user.module.ts
import { Module } from "@nestjs/common"
import { ConfigModule } from "@nestjs/config"
import { createNevoNatsClient } from "@riaskov/nevo-messaging"
import { UserController } from "./user.controller"
import { UserService } from "./user.service"
@Module({
imports: [ConfigModule],
controllers: [UserController],
providers: [
UserService,
createNevoNatsClient(["COORDINATOR"], {
clientIdPrefix: "user",
servers: ["nats://127.0.0.1:4222"]
})
]
})
export class UserModule {}// main.ts
import { createNatsMicroservice } from "@riaskov/nevo-messaging"
import { AppModule } from "./app.module"
createNatsMicroservice({
microserviceName: "user",
module: AppModule,
port: 8086
})@Injectable()
export class OrderService extends NatsClientBase {
constructor(@Inject("NEVO_NATS_CLIENT") client: NevoNatsClient) {
super(client)
}
async place(userId: bigint) {
const user = await this.query("user", "user.getById", { id: userId })
await this.emit("notifications", "order.created", { userId: user.id })
}
}docker run --rm -p 4222:4222 nats:2 -jsJetStream is enabled with -js so subscriptions with { ack: true } work out of the box.
// Request/response
const user = await this.query("user", "user.getById", { id: 123n })
// Fire-and-forget
await this.emit("notifications", "user.created", { userId: 123n })
// Publish / subscribe (durable JetStream consumer)
const sub = await this.subscribe(
"user", "user.updated",
{ ack: true, durable: "audit" },
async (msg, ctx) => { await project(msg); await ctx.ack() }
)
// Broadcast to every connected consumer
await this.broadcast("system.status", { ok: true })See docs/messaging-patterns.md.
| Topic | Doc |
|---|---|
| Other transports (Kafka, HTTP, HTTP/2, WS, Socket.IO) | docs/ |
| DevTools live dashboard | docs/devtools.md |
| Reliable patterns (outbox, inbox, saga, CQRS, DLQ) | docs/outbox.md |
Resilience decorators (@Hedge, @CircuitBreaker, @Adaptive, @Backpressure) |
docs/resilience-decorators.md |
| Resilience (retry, breaker, hedging, rate limit) | docs/retry.md |
| Distributed idempotency (Redis store) | docs/idempotency.md |
| Service discovery (Consul, Kubernetes DNS, Etcd, Eureka, AWS Cloud Map, Nomad) | docs/discovery.md |
| Production storage matrix (Postgres, Redis, SQLite) | docs/storage-matrix.md |
| Testing with in-memory transport | docs/testing.md |
| Observability (OTel, metrics, health probes) | docs/observability.md |
| Security (ACL, JWT/JWKS, mTLS) | docs/security.md |
| Performance tuning | docs/performance.md |
Full index: docs/README.md.
examples/nats-user— NATS request/response + publish/subscribe + broadcastexamples/user— standard Kafka microserviceexamples/socket-user— Socket.IO transportexamples/http-user— HTTP query/emit + SSE subscribe + broadcastexamples/resilience-decorators—@Hedge/@CircuitBreaker/@Adaptive/@Backpressureplus the Redis idempotency store and Consul / Kubernetes DNS discovery providers
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit (
git commit -m "Add amazing feature") - Push (
git push origin feature/amazing-feature) - Open a Pull Request
MIT — see LICENSE.
- Issues: github.com/ARyaskov/nevo-messaging/issues
- Documentation: docs/
- Examples: examples/