A modular, transport-agnostic microservices framework for Elysia
Build production-ready microservices with Elysia's speed and simplicity
- π Plugin Mode - Seamless integration with Elysia (HTTP + Microservice)
- β‘ Standalone Mode - Pure microservice applications without HTTP
- π― Advanced Pattern Matching - Wildcards (
user.*), regex, and catchall handlers - π‘οΈ Guards & Middleware - Hierarchical DI system with global, group, and handler scopes
- π Middleware & Guards - Authorization guards, request enrichment middleware, cross-cutting concerns
- π Transport Agnostic - Support for TCP, TLS, NATS, Redis, and Kafka
- π¦ Modular - Install only what you need, tree-shakable bundles
- π Service Discovery - Static and DNS-based service discovery
- βοΈ Load Balancing - Round-robin with failure tracking
- π‘οΈ Resilience - Circuit breaker, retries, and timeouts
- π Chaos Engineering - Inject failures and latency for testing
- π NestJS Compatible - Use NestJS decorators with Elysia
- π§© Parameter Decorators -
@Payload(),@Ctx(), and@App()for handler injection - π Connection Pooling - Automatic client pooling with failover
- πͺ Lifecycle Hooks - onBefore/onAfter hooks for cross-cutting concerns
- π₯ Health Checks - Built-in health and readiness endpoints (hybrid mode)
- π TypeScript First - Full type safety with excellent IntelliSense
- Getting Started - Quick start guide for new users
- Pattern Matching - Wildcards, regex, and catchall handlers
- Advanced Features - Hooks, error handling, resilience patterns
- API Reference - Complete API documentation
- Architecture - System design and architecture
- Migration Guide - Upgrading from previous versions
- Changelog - Version history and release notes
- Contributing - How to contribute to this project
- Code of Conduct - Community guidelines
This monorepo contains the following packages:
- @elysia-microservice/core - Core functionality (registry, protocol, patterns, context)
- @elysia-microservice/utils - Service discovery, load balancing, client pooling, chaos engineering
- @elysia-microservice/transport-tcp - TCP transport server
- @elysia-microservice/transport-tls - TLS/SSL transport server
- @elysia-microservice/transport-nats - NATS transport server
- @elysia-microservice/transport-redis - Redis transport server
- @elysia-microservice/transport-kafka - Kafka transport server
- @elysia-microservice/client-tcp - TCP client
- @elysia-microservice/client-tls - TLS/SSL client
- @elysia-microservice/client-nats - NATS client
- @elysia-microservice/client-redis - Redis client
- @elysia-microservice/client-kafka - Kafka client
- @elysia-microservice/client-base - Client factory, proxy, and resilience
- @elysia-microservice/adapters - Framework adapters (NestJS compatibility)
# Core + TCP transport (simplest setup)
bun add @elysia-microservice/core @elysia-microservice/transport-tcp @elysia-microservice/client-tcp elysiaserver.ts
import { Elysia } from 'elysia';
import { Microservice } from '@elysia-microservice/core';
const app = new Elysia()
.use(Microservice({
server: { transport: 'tcp', options: { port: 4000 } },
hybrid: true
}))
.onMsMessage('user.get', async (ctx) => {
return { id: ctx.data.id, name: 'John Doe' };
})
.onMsEvent('user.created', (ctx) => {
console.log('User created:', ctx.data);
})
.get('/', () => 'Hello HTTP!')
.listen(3000);
console.log('π HTTP: http://localhost:3000');
console.log('π Microservice: tcp://localhost:4000');client.ts
import { createTcpClient } from '@elysia-microservice/client-tcp';
const client = createTcpClient({ host: '127.0.0.1', port: 4000 });
// Request/response
const user = await client.send('user.get', { id: 1 });
console.log(user); // { id: 1, name: 'John Doe' }
// Fire-and-forget event
await client.emit('user.created', { id: 2, name: 'Jane' });
await client.close();π Read the full Getting Started Guide
Messages (Request/Response):
- Client waits for response
- Use
.onMsMessage()on server,.send()on client - For queries and commands needing confirmation
Events (Fire-and-Forget):
- Client doesn't wait for response
- Use
.onMsEvent()on server,.emit()on client - For notifications and side effects
// Exact match
.onMsMessage('user.get', handler)
// Wildcard - matches user.create, user.update, etc.
.onMsMessage('user.*', handler)
// Regex - matches user.create or user.update only
.onMsMessage(/^user\.(create|update)$/, handler)
// Catchall - handles unmatched patterns
.onMsCatchallMessage((pattern, data) => {
return { error: 'Pattern not found' };
})Learn more about Pattern Matching β
All handlers receive a structured context:
.onMsMessage('user.*', (ctx) => {
console.log(ctx.pattern); // Matched pattern: "user.create"
console.log(ctx.data); // Payload: { name: "John" }
console.log(ctx.meta); // Transport metadata
return { success: true };
})const app = new Elysia()
.use(Microservice({
hybrid: true,
server: { transport: 'tcp', options: { port: 4000 } },
clients: {},
adapters: [
{
class: NestAdapter,
initializer: (adapter, registry) => {
adapter.init(registry, new UserController());
},
},
],
}));Adapters let you register controller classes once, each adapter can optionally receive an initializer to wire controllers.
Use the Nest adapter with familiar method decorators and parameter injections:
- Method decorators:
@MessagePattern()(request/response),@EventPattern()(fire-and-forget) - Parameter decorators:
@Payload(),@Ctx(),@App()
To use decorators, update the following in your tsconfig.json file:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true // optional, but common with Nest-style decorators
}
}import { MessagePattern, EventPattern, Payload, Ctx, App } from '@elysia-microservice/core';
import type { MicroserviceContext } from '@elysia-microservice/core';
import type { ElysiaInstance } from 'elysia';
import { from, Observable } from 'rxjs';
class UserController {
@MessagePattern('user.get')
getUser(
@Payload('id') id: number,
@Ctx() ctx: MicroserviceContext,
@App() app: ElysiaInstance
) {
app.log?.info?.(`Request trace: ${ctx.traceId}`);
return { id, name: 'John Doe' };
}
// Event handler can also return an Observable stream
@EventPattern('user.activity')
activityStream(): Observable<number> {
return from([1, 2, 3]);
}
}bun add @elysia-microservice/transport-tcp @elysia-microservice/client-tcpbun add @elysia-microservice/transport-tls @elysia-microservice/client-tlsbun add @elysia-microservice/transport-nats @elysia-microservice/client-nats natsbun add @elysia-microservice/transport-redis @elysia-microservice/client-redis redisbun add @elysia-microservice/transport-kafka @elysia-microservice/client-kafka kafkajscd base
bun install
make build# Show all available commands
make help
# Build packages
make build # Build all packages
make rebuild # Clean and rebuild
# Run tests
make test # All tests
make test-unit # Unit tests only
make quick-test # Fast unit tests (no build)
# Development
make dev # Watch mode
make check # Quick validation (build + test + lint)
make validate # Full validation (clean + install + build + test)
# Publishing (maintainers only)
make version VERSION=0.2.0 # Update version
make publish-dry # Test publish
make publish # Publish to npmmake test # All tests
make test-unit # Unit tests only
make test-integration # Integration testsmake cleanWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Commit your changes (
git commit -m 'feat(core): add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please read our Code of Conduct before contributing.
MIT License - see LICENSE file for details.
- Elysia - The web framework we build on
- Bun - The JavaScript runtime we recommend
- Documentation - Full documentation
- Examples - Example applications
- GitHub Issues - Report bugs or request features
- GitHub Discussions - Ask questions and share ideas