Koa + TypeScript + IOC = Koatty. Koatty is a progressive Node.js framework for building efficient and scalable server-side applications. It's perfect for crafting enterprise-level APIs, microservices, and full-stack applications with TypeScript excellence.
- 🚄 High Performance: Built on top of Koa with optimized architecture
- 🧩 Full-Featured: Supports gRPC, HTTP, WebSocket, scheduled tasks, and more
- 🧠 TypeScript First: Native TypeScript support with elegant OOP design
- 🌀 Spring-like IOC Container: Powerful dependency injection system with autowiring
- ✂️ AOP Support: Aspect-oriented programming with decorator-based interceptors
- 🔌 Extensible Architecture: Plugin system with dependency injection
- 📦 Modern Tooling: CLI scaffolding, testing utilities, and production-ready configurations
- 🌐 Protocol Agnostic: Write once, deploy as HTTP/gRPC/WebSocket services
- ✅ Multi-Protocol Architecture - Run HTTP, HTTPS, HTTP/2, HTTP/3, gRPC, WebSocket, and GraphQL simultaneously
- ✅ Intelligent Metadata Cache - LRU caching with preloading for 70%+ performance boost
- ✅ Protocol-Specific Middleware - Bind middleware to specific protocols with
@Middleware({ protocol: [...] }) - ✅ Graceful Shutdown - Enhanced connection pool management and cleanup handlers
- ✅ Enhanced gRPC Support - Timeout detection, duplicate call protection, streaming improvements
- ✅ Application Lifecycle Hooks - Custom decorators with
@OnEventdecorator API for framework lifecycle events - ✅ Version Conflict Detection - Automatic detection and resolution of dependency conflicts
- ✅ GraphQL over HTTP/2 - Automatic HTTP/2 upgrade with SSL for multiplexing and compression
- ✅ Global Exception Handling -
@ExceptionHandler()decorator for centralized error management - ✅ OpenTelemetry Tracing - Full-stack observability with distributed tracing
- 💪 Swagger/OpenAPI 3.0 - Automatic API documentation generation
Koatty now supports running multiple protocols simultaneously on different ports. Configure multiple servers easily:
// config/config.tsexportdefault{
...
server: {hostname: '127.0.0.1',port: 3000,protocol: ["http","grpc"],// Multiple protocols: 'http' | 'https' | 'http2' | 'http3' | 'grpc' | 'ws' | 'wss' | 'graphql'trace: false,},
...
}Single Protocol (backward compatible):
// config/config.tsexportdefault{server: {protocol: "grpc",// Single protocol}}Multi-Protocol Router Configuration:
When using multiple protocols, configure protocol-specific extensions in config/router.ts:
// config/router.tsexportdefault{ext: {// HTTP protocol config (optional)
...,// gRPC protocol config (optional)protoFile: "./resource/proto/Hello.proto",poolSize: 10,streamConfig: {messageCount: 50}// WebSocket protocol config (optional)maxFrameSize: 1024*1024,heartbeatInterval: 15000,maxConnections: 1000}}How It Works:
koatty_serveautomatically creates server instances for each protocolkoatty_routercreates dedicated router instances for each protocol- Controllers are automatically registered to appropriate routers based on their decorators
- HTTP controllers (
@Controller) work with HTTP/HTTPS/HTTP2 - gRPC controllers (
@GrpcController) work with gRPC - GraphQL controllers (
@GraphQLController) work with GraphQL (over HTTP/HTTPS) - WebSocket controllers (
@WsController) work with WebSocket
Important Notes:
GraphQL Protocol: GraphQL is an application-layer protocol that runs over HTTP/HTTP2, not a separate transport protocol. When you specify
protocol: "graphql", Koatty automatically:- Uses HTTP as transport by default
- Uses HTTP/2 when SSL certificates are configured (recommended for production)
GraphQL over HTTP/2 (Recommended): HTTP/2 provides significant benefits for GraphQL:
- Multiplexing: Handle multiple queries over a single connection
- Header Compression: Reduce bandwidth for large queries
- Server Push: Prefetch related resources
- HTTP/1.1 Fallback: Automatic downgrade for compatibility
To enable HTTP/2 for GraphQL, configure in
config/config.ts:// config/config.tsexportdefault{server: {protocol: "graphql",ssl: {mode: 'auto',key: './ssl/server.key',cert: './ssl/server.crt'},ext: {maxConcurrentStreams: 100// Optional: HTTP/2 config}}}
And configure GraphQL schema in
config/router.ts:// config/router.tsexportdefault{ext: {schemaFile: "./resource/graphql/schema.graphql"}}
Enhanced Features:
- ✅ Intelligent Metadata Cache - LRU caching mechanism, significantly improves performance
- ✅ Metadata Preloading - Preload at startup, optimize component registration
- ✅ Version Conflict Detection - Automatically detect and resolve dependency version conflicts
- ✅ Circular Dependency Detection - Circular dependency detection and resolution suggestions
@Service()exportclassUserService{asyncfindUser(id: number){return{ id,name: 'Koatty User'};}}
@Controller()exportclassIndexController{app: App;ctx: KoattyContext;
@Config("server")conf: {protocol: string|string[]};
...
@Autowired()privateuserService: UserService;asynctest(id: number){constinfo=awaitthis.userService.findUser(id);
...
}}Performance Improvements:
// In Loader.ts - Metadata is now preloaded for optimal performanceIOC.preloadMetadata();// Preload all metadata to populate cache// Intelligent caching reduces reflect operations by 70%+// Cache hits: ~95% in typical applicationsDifferent controllers for different protocols:
// HTTP Controller
@Controller('/api')exportclassUserController{
@GetMapping('/users/:id')asyncgetUser(@PathVariable('id')id: string){return{ id,name: 'User'};}}// gRPC Controller
@GrpcController('/Hello')exportclassHelloController{
@PostMapping('/SayHello')
@Validated()asyncsayHello(@RequestBody()params: SayHelloRequestDto): Promise<SayHelloReplyDto>{constres=newSayHelloReplyDto();res.message=`Hello, ${params.name}!`;returnres;}}// GraphQL Controller (runs over HTTP/HTTPS)
@GraphQLController('/graphql')exportclassUserController{
@GetMapping()asyncgetUser(@RequestParam()id: string): Promise<User>{return{ id,name: 'GraphQL User'};}
@PostMapping()asynccreateUser(@RequestParam()input: UserInput): Promise<User>{return{id: input.id,name: input.name};}}@Aspect()exportclassLogAspectimplementsIAspect{app: App;run(){console.log('LogAspect');}}// Apply aspect to controller
@Controller()
@BeforeEach(LogAspect)exportclassUserController{
...
@After(LogAspect)test(){
...
}}Protocol-Specific Middleware:
// Middleware can now be bound to specific protocols
@Middleware({protocol: ["http","https"]})exportclassHttpOnlyMiddlewareimplementsIMiddleware{run(options: any,app: App){returnasync(ctx: KoattyContext,next: Function)=>{// This middleware only runs for HTTP/HTTPS protocolsconsole.log('HTTP request:',ctx.url);awaitnext();};}}Plugin System:
// plugin/logger.tsexportclassLoggerPluginimplementsIPlugin{app: App;run(){// Hook into application lifecycle eventsLogger.Debug("LoggerPlugin");returnPromise.resolve();}}Application Lifecycle Events:
// Use @OnEvent to hook into application lifecycle events
@Component("MyComponent",{scope: 'user',priority: 50,description: 'Custom component example'})exportclassMyComponent{// Execute when router loads
@OnEvent(AppEvent.loadRouter)asyncinitRouter(app: KoattyApplication){console.log('Initializing router...');// Custom router initialization logic}// Execute when application is ready
@OnEvent(AppEvent.appReady)asynconReady(app: KoattyApplication){console.log('Application ready');// Service registration, connection pool initialization, etc.}// Execute when application stops
@OnEvent(AppEvent.appStop)asynccleanup(app: KoattyApplication){console.log('Cleaning up resources...');// Close connections, release resources}}| Framework | Requests/sec | Latency | Memory Usage |
|---|---|---|---|
| Koatty | 12,321 | 1.43ms | 54MB |
| Express | 12,456 | 1.45ms | 52MB |
| NestJS | 11,892 | 1.51ms | 63MB |
Tested on AWS t3.micro with 100 concurrent connections
- Install CLI:
npm install -g koatty_cli- Create Project:
koatty new awesome-app- Run Development Server:
cd awesome-app
npm run devThanks to these amazing developers:
BSD-3 © Koatty Team