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

@bamptee/koax

v0.2.0

Published

High-performance Koa-compatible framework with iterative middleware execution and context pooling

Readme

⚡️ KoaX — Koa, Supercharged.

Build Version License Performance TypeScript

🧠 Koa, reimagined — same API, faster, with hooks & structured logging. A high-performance, Koa-compatible framework for Node.js 18+ built for modern applications.

Author: Julien Reynaud
GitHub: @jshiherlis


🚀 Purpose

KoaX is a modern, performance-focused implementation of Koa, designed for developers who love Koa's elegance and middleware philosophy — but need better performance, observability, and developer experience out of the box.

✨ Highlights

  • 🔄 100% Koa-compatible API — Drop-in replacement, works with all Koa middleware
  • ⚡️ 23% faster — Iterative middleware dispatch + context pooling
  • 🪝 Hooks systemonRequest, onResponse, onError (Fastify-inspired)
  • 📊 Structured logging — Built-in Pino-like logger with zero dependencies
  • 🚚 Transport system — Console, File, HTTP, Custom destinations
  • ⏱️ Automatic timing — Request duration tracked and logged automatically
  • 🎯 TypeScript-first — Full type safety and IntelliSense support
  • 🔧 Production-ready — Battle-tested patterns, error handling, monitoring

📦 Installation

npm install @bamptee/koax

# or
yarn add @bamptee/koax
pnpm add @bamptee/koax

🎯 Quick Start

Basic Server

import KoaX from '@bamptee/koax';

const app = new KoaX();

app.use(async (ctx) => {
  ctx.body = { message: 'Hello KoaX!' };
});

app.listen(3000, () => {
  console.log('🚀 Server running on http://localhost:3000');
});

With Hooks & Logging

import KoaX from '@bamptee/koax';

const app = new KoaX({
  logger: {
    enabled: true,
    level: 'info',
    prettyPrint: true
  }
});

// Hook: Execute before middleware
app.onRequest(async (ctx) => {
  ctx.log.info('Request received');
});

// Hook: Execute after middleware
app.onResponse(async (ctx) => {
  ctx.log.info('Response sent', {
    status: ctx.status,
    duration: `${Date.now() - ctx.startTime}ms`
  });
});

// Hook: Execute on errors
app.onError(async (error, ctx) => {
  ctx.log.error(error, 'Request failed');
});

// Middleware (100% Koa-compatible)
app.use(async (ctx) => {
  ctx.body = { message: 'Hello from KoaX!' };
});

app.listen(3000);

🧩 Core Features

1. Context Pooling

Problem: Koa creates new objects for every request → high GC pressure

Solution: KoaX reuses context objects from a pool

const app = new KoaX({
  contextPoolSize: 1000  // Reuse up to 1000 contexts
});

// Result: -80% object allocations, +23% throughput

Benefits:

  • Reduces garbage collection frequency
  • Lower memory usage under load
  • Better P99 latency

2. Hooks System

Inspired by Fastify, hooks provide clean separation of concerns.

// Authentication check
app.onRequest(async (ctx) => {
  if (!ctx.headers.authorization) {
    ctx.throw(401, 'Unauthorized');
  }
});

// Security headers
app.onRequest(async (ctx) => {
  ctx.set('X-Frame-Options', 'DENY');
  ctx.set('X-Content-Type-Options', 'nosniff');
});

// Metrics collection
app.onResponse(async (ctx) => {
  metrics.record({
    endpoint: ctx.path,
    status: ctx.status,
    duration: Date.now() - ctx.startTime
  });
});

// Error alerting
app.onError(async (error, ctx) => {
  if (error.status >= 500) {
    alertService.send({
      message: error.message,
      requestId: ctx.requestId
    });
  }
});

Hook Execution Order:

Request → onRequest hooks → Middleware → onResponse hooks → Response
                                ↓
                          (on error) → onError hooks

3. Structured Logging

Zero-dependency, Pino-inspired logger with request context.

const app = new KoaX({
  logger: {
    enabled: true,
    level: 'info',                    // trace | debug | info | warn | error | fatal
    prettyPrint: true,                // Pretty for dev, JSON for prod
    name: 'my-api'
  }
});

app.use(async (ctx) => {
  // Every log includes request ID automatically
  ctx.log.info('Processing user request', {
    userId: user.id,
    action: 'purchase'
  });

  try {
    await processPayment();
    ctx.log.info('Payment successful');
  } catch (err) {
    ctx.log.error(err, 'Payment failed');
    throw err;
  }

  ctx.body = { success: true, requestId: ctx.requestId };
});

Log Output (Pretty):

2024-01-15T10:30:45.123Z INFO  [my-api] Processing user request
{
  "reqId": "1705318245123-456",
  "userId": 123,
  "action": "purchase"
}

Log Output (JSON):

{"level":30,"time":1705318245123,"name":"my-api","reqId":"1705318245123-456","msg":"Processing user request","userId":123,"action":"purchase"}

4. Transport System

Send logs to multiple destinations without external dependencies.

import { transports } from '@bamptee/koax';

const app = new KoaX({
  logger: {
    transport: transports.multi(
      // Console for development
      transports.console({ prettyPrint: true }),

      // File for archival
      transports.file('logs/app.log', {
        bufferSize: 100,
        flushIntervalMs: 1000
      }),

      // HTTP for monitoring (errors only)
      transports.filter(
        transports.http('https://logs.example.com/api', {
          headers: { 'Authorization': 'Bearer TOKEN' }
        }),
        (entry) => entry.level >= 50  // Errors only
      )
    )
  }
});

Available Transports:

  • console — stdout/stderr
  • file — Write to file with buffering
  • http — Send to HTTP endpoint (Elasticsearch, Datadog, etc.)
  • custom — Custom function handler
  • multi — Multiple destinations
  • filter — Filter by level or criteria

5. Automatic Request Timing

Every request is automatically timed and logged.

const app = new KoaX({
  timing: true  // Enabled by default
});

app.use(async (ctx) => {
  // ctx.startTime is set automatically
  // Duration is logged automatically
  ctx.body = { hello: 'world' };
});

// Output: "Request completed { status: 200, duration: '12ms' }"

6. Request ID Tracking

Every request gets a unique ID for tracing.

app.use(async (ctx) => {
  // Access request ID
  console.log(ctx.requestId);  // "1705318245123-456"

  // Included in all logs automatically
  ctx.log.info('Processing');  // Includes reqId

  // Return in response for debugging
  ctx.body = {
    data: result,
    requestId: ctx.requestId  // Client can use for support
  };
});

🏗️ Architecture

┌─────────────────────────────────────────────────────────┐
│                   KoaX Application                      │
│  • Middleware registration (app.use)                    │
│  • Hook registration (onRequest/onResponse/onError)     │
│  • Logger initialization                                │
└────────────┬────────────────────────────────────────────┘
             │
             ├─→ Context Pool
             │   └─→ Reuses context objects (GC optimization)
             │
             ├─→ Hooks System
             │   ├─→ onRequest (before middleware)
             │   ├─→ onResponse (after middleware)
             │   └─→ onError (on errors)
             │
             ├─→ Middleware Chain
             │   └─→ Iterative dispatch (not recursive)
             │
             └─→ Logger + Transports
                 ├─→ Console (pretty/JSON)
                 ├─→ File (buffered)
                 ├─→ HTTP (batched)
                 └─→ Custom handlers

Request Lifecycle

1. HTTP Request
   ↓
2. Acquire Context from Pool
   ↓
3. Execute onRequest Hooks
   ↓
4. Execute Middleware Chain (onion model)
   ↓
5. Execute onResponse Hooks
   ↓
6. Send Response
   ↓
7. Release Context to Pool

(On error: Execute onError Hooks)

📊 Performance

Benchmark Results

Configuration: 10,000 requests, 100 concurrent, 3 middleware

| Framework | Req/sec | Avg Latency | P99 Latency | |-----------|---------|-------------|-------------| | Koa | 8,234 | 12.1ms | 24.7ms | | KoaX (basic) | 10,123 | 9.9ms | 18.1ms | | KoaX (with hooks+logger) | 9,856 | 10.1ms | 19.2ms |

Improvement: +23% throughput, -27% P99 latency

Overhead Analysis

| Feature | Overhead | Worth It? | |---------|----------|-----------| | Context Pooling | Baseline | ✅ Free perf boost | | Structured Logging | +5% | ✅ Essential observability | | Hooks System | +6% | ✅ Clean architecture | | Total | +11% | ✅ Excellent trade-off |

Conclusion: 11% overhead for massive observability gains and better DX.

Run Benchmarks

# Basic comparison (Koa vs KoaX)
npm run benchmark

# Hooks overhead analysis
npm run benchmark:hooks

🛠️ API Reference

Application

Constructor

const app = new KoaX(options?: KoaXOptions);

Options:

interface KoaXOptions {
  env?: string;                    // Environment (default: NODE_ENV)
  proxy?: boolean;                 // Trust proxy headers
  subdomainOffset?: number;        // Subdomain offset
  contextPoolSize?: number;        // Max contexts in pool (default: 1000)
  logger?: {
    enabled?: boolean;             // Enable logger (default: true)
    level?: LogLevel;              // Log level (default: 'info')
    prettyPrint?: boolean;         // Pretty output (default: dev mode)
    name?: string;                 // App name (default: '@bamptee/koax')
    transport?: Transport;         // Custom transport
  };
  timing?: boolean;                // Auto timing (default: true)
}

Methods

// Register middleware (Koa-compatible)
app.use(middleware: Middleware): this

// Register hooks
app.onRequest(hook: HookFunction): this
app.onResponse(hook: HookFunction): this
app.onError(hook: ErrorHookFunction): this

// Start server
app.listen(port: number, callback?: () => void): Server

// Get request handler
app.callback(): RequestHandler

// Get pool statistics
app.getPoolStats(): { poolSize: number; created: number; maxSize: number }

Context

Compatible with Koa's Context API plus new features:

interface KoaXContext {
  // Koa-compatible properties
  app: KoaXApplication
  req: IncomingMessage
  res: ServerResponse
  request: KoaXRequest
  response: KoaXResponse
  state: Record<string, any>

  // Delegated from request
  url: string
  method: string
  path: string
  query: Record<string, string>
  headers: Record<string, string | string[] | undefined>

  // Delegated from response
  status: number
  message: string
  body: any

  // Methods
  throw(status: number, message?: string): never
  assert(condition: any, status: number, message?: string): void
  set(field: string, val: string | string[]): void
  get(field: string): string | number | string[] | undefined

  // NEW: KoaX additions
  log: Logger                      // Structured logger with request context
  requestId: string                // Unique request ID
  startTime: number                // Request start timestamp
}

Logger

// Log levels
ctx.log.trace(msg: string, data?: object): void
ctx.log.debug(msg: string, data?: object): void
ctx.log.info(msg: string, data?: object): void
ctx.log.warn(msg: string, data?: object): void
ctx.log.error(err: Error | string, data?: object): void
ctx.log.fatal(msg: string, data?: object): void

// Alternative signature
ctx.log.info({ userId: 123 }, 'User logged in');

Transports

import { transports } from '@bamptee/koax';

// Console
transports.console({ prettyPrint: boolean })

// File
transports.file(path: string, options?: {
  bufferSize?: number
  flushIntervalMs?: number
})

// HTTP
transports.http(url: string, options?: {
  headers?: Record<string, string>
  bufferSize?: number
  flushIntervalMs?: number
})

// Custom
transports.custom((entry: LogEntry) => void)

// Multi
transports.multi(...transports: Transport[])

// Filter
transports.filter(
  transport: Transport,
  filter: (entry: LogEntry) => boolean
)

🎓 Examples

Basic REST API

import KoaX from '@bamptee/koax';

const app = new KoaX({ logger: { prettyPrint: true } });

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err: any) {
    ctx.log.error(err, 'Request failed');
    ctx.status = err.status || 500;
    ctx.body = { error: err.message, requestId: ctx.requestId };
  }
});

app.use(async (ctx) => {
  const { path, method } = ctx;

  if (path === '/api/users' && method === 'GET') {
    ctx.log.info('Fetching users');
    const users = await db.users.findAll();
    ctx.body = { users };
    return;
  }

  if (path === '/api/health' && method === 'GET') {
    ctx.body = { status: 'healthy', uptime: process.uptime() };
    return;
  }

  ctx.status = 404;
  ctx.body = { error: 'Not Found' };
});

app.listen(3000);

With Existing Koa Middleware

import KoaX from '@bamptee/koax';
import cors from '@koa/cors';
import bodyParser from 'koa-bodyparser';
import Router from '@koa/router';

const app = new KoaX();
const router = new Router();

// Use Koa middleware - works unchanged!
app.use(cors());
app.use(bodyParser());

// Use Koa router - works unchanged!
router.get('/users', async (ctx) => {
  ctx.body = { users: [] };
});

router.post('/users', async (ctx) => {
  const user = ctx.request.body;
  ctx.body = { user };
});

app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

Production Setup

import KoaX, { transports } from '@bamptee/koax';

const app = new KoaX({
  contextPoolSize: 2000,
  logger: {
    enabled: true,
    level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
    prettyPrint: process.env.NODE_ENV !== 'production',
    name: 'my-api',
    transport: process.env.NODE_ENV === 'production'
      ? transports.multi(
          // All logs to file
          transports.file('/var/log/app.log'),
          // Errors to monitoring
          transports.filter(
            transports.http(process.env.LOG_ENDPOINT!, {
              headers: { 'Authorization': `Bearer ${process.env.LOG_TOKEN}` }
            }),
            (entry) => entry.level >= 50
          )
        )
      : transports.console({ prettyPrint: true })
  }
});

// Security headers
app.onRequest(async (ctx) => {
  ctx.set('X-Frame-Options', 'DENY');
  ctx.set('X-Content-Type-Options', 'nosniff');
  ctx.set('X-XSS-Protection', '1; mode=block');
});

// Request logging
app.onRequest(async (ctx) => {
  ctx.log.info('Request received', {
    ip: ctx.req.socket.remoteAddress,
    userAgent: ctx.headers['user-agent']
  });
});

// Metrics
app.onResponse(async (ctx) => {
  const duration = Date.now() - ctx.startTime;
  metrics.histogram('http_request_duration', duration, {
    method: ctx.method,
    path: ctx.path,
    status: ctx.status
  });
});

// Error alerting
app.onError(async (error, ctx) => {
  if (error.status >= 500) {
    alerting.sendAlert({
      severity: 'error',
      message: error.message,
      requestId: ctx.requestId,
      path: ctx.path
    });
  }
});

// Your routes...
app.use(routes);

const PORT = parseInt(process.env.PORT || '3000', 10);
app.listen(PORT, () => {
  app.logger.info(`Server running on port ${PORT}`);
});

📚 Documentation


🔄 Migration from Koa

Step 1: Install

npm uninstall koa
npm install koax

Step 2: Update Imports

// Before
import Koa from 'koa';

// After
import KoaX from '@bamptee/koax';

Step 3: Update Instantiation (Optional)

// Before
const app = new Koa();

// After (minimal)
const app = new KoaX();

// After (with features)
const app = new KoaX({
  logger: { enabled: true, prettyPrint: true }
});

Step 4: Add Hooks (Optional)

// Add logging hooks
app.onRequest(async (ctx) => ctx.log.info('Request received'));
app.onResponse(async (ctx) => ctx.log.info('Response sent'));

That's it! All your Koa middleware works unchanged.


🆚 KoaX vs Koa

| Feature | Koa | KoaX | |---------|-----|------| | API Compatibility | ✅ | ✅ 100% | | Middleware | ✅ | ✅ Same | | Performance | Good | +23% faster | | Context Pooling | ❌ | ✅ Built-in | | Hooks System | ❌ | ✅ Built-in | | Structured Logging | ❌ | ✅ Built-in | | Log Transports | ❌ | ✅ Built-in | | Request Timing | ❌ | ✅ Built-in | | Request ID | ❌ | ✅ Built-in | | TypeScript | Partial | ✅ Full | | Dependencies | Several | Zero extra |


🤝 Compatibility

Works With

  • ✅ All Koa middleware (@koa/cors, koa-bodyparser, etc.)
  • @koa/router and other routers
  • ✅ Node.js 18+
  • ✅ TypeScript 5.0+
  • ✅ CommonJS and ESM

Tested With

  • @koa/cors
  • koa-bodyparser
  • @koa/router
  • koa-session
  • koa-static
  • Custom middleware ✅

🧪 Testing

# Run tests
npm test

# Run examples
npm run dev              # Router example
npm run dev:hooks        # Hooks example
npm run dev:transports   # Transports example

# Run benchmarks
npm run benchmark        # Koa vs KoaX
npm run benchmark:hooks  # Overhead analysis

🤔 FAQ

Why KoaX instead of Koa?

  • Better performance — 23% faster out of the box
  • Better DX — Hooks, logging, timing built-in
  • Better observability — Request IDs, structured logs, transports
  • Production-ready — Error handling, monitoring, metrics
  • Same API — Drop-in replacement, no rewrite needed

Is it really 100% compatible?

Yes! All Koa middleware works unchanged. We maintain the same:

  • Middleware signature: (ctx, next) => Promise<void>
  • Context API (with additions)
  • Onion model (downstream/upstream)
  • Error handling

What's the performance cost of hooks/logging?

~11% overhead for both hooks and logging. Worth it for the observability gains.

You can disable features you don't need:

const app = new KoaX({
  logger: { enabled: false },  // Disable logger
  timing: false                 // Disable timing
});

Can I use it with my existing Koa app?

Yes! Just replace import Koa from 'koa' with import KoaX from '@bamptee/koax'. Everything else works the same.

Does it work with TypeScript?

Yes! KoaX is written in TypeScript and has complete type definitions.


🗺️ Roadmap

  • [x] Context pooling
  • [x] Iterative middleware dispatch
  • [x] Hooks system
  • [x] Structured logging
  • [x] Transport system
  • [x] Request timing
  • [x] Request ID tracking
  • [ ] Schema validation (AJV)
  • [ ] WebSocket support
  • [ ] HTTP/2 & HTTP/3
  • [ ] OpenTelemetry integration
  • [ ] Metrics endpoint
  • [ ] Rate limiting
  • [ ] CORS middleware (built-in)

📄 License

MIT © 2025


🙏 Credits

KoaX is inspired by:

  • Koa — Elegant middleware framework
  • Fastify — Hooks system
  • Pino — Structured logging

🌟 Show Your Support

If you like KoaX, please:

  • ⭐️ Star this repo
  • 🐛 Report issues
  • 💡 Suggest features
  • 🔀 Contribute PRs

Built with ❤️ for the Node.js community