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

@sayansenapati/express-pro

v1.0.0

Published

High-performance native HTTP server - 8x faster than Express.js

Readme

Express-Pro

High-performance native HTTP server for Node.js with platform-specific async I/O. Built on io_uring (Linux), kqueue (macOS), and IOCP (Windows) for maximum throughput with minimal latency.

┌─────────────────────────────────────────────────────────────────┐
│  Performance                                                    │
│  ───────────                                                    │
│  Linux + io_uring:    500,000+ req/s                           │
│  macOS + kqueue:      150,000+ req/s                           │
│  Windows + IOCP:      100,000+ req/s                           │
│  Express.js:          ~20,000 req/s                            │
│                                                                 │
│  Up to 25x faster than traditional Node.js HTTP servers        │
└─────────────────────────────────────────────────────────────────┘

Table of Contents

Installation

npm install express-pro

Platform Prerequisites

Linux (Recommended)

  • Kernel 5.1+ with io_uring support
  • liburing development headers:
    # Ubuntu/Debian
    sudo apt-get install liburing-dev
    
    # Fedora/RHEL
    sudo dnf install liburing-devel
    
    # Arch
    sudo pacman -S liburing

macOS

  • macOS 10.14+ (no additional dependencies)

Windows

  • Windows 10/Server 2016+ (no additional dependencies)

Quickstart

const expresspro = require('express-pro');

// Create application instance
const app = expresspro();

// Middleware support
app.use((req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next();
});

// Route handlers
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: Date.now() });
});

app.get('/users/:id', (req, res) => {
  res.json({
    id: req.params.id,
    query: req.query
  });
});

app.post('/users', (req, res) => {
  res.status(201).json({
    message: 'User created',
    body: req.body
  });
});

// Error handling
app.onError((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: err.message });
});

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

API Reference

ExpressPro(options?)

Creates a new Express-Pro application instance.

const expresspro = require('express-pro');

// Default options
const app = expresspro();

// With custom options
const app = expresspro({
  initialBufferSize: 32768,
  maxBodySize: 5242880,  // 5MB
  streamBody: false
});

Application Methods

app.use(path?, ...handlers)

Register middleware for all routes.

// Global middleware
app.use((req, res, next) => {
  res.set('X-Request-Id', generateId());
  next();
});

// Path-specific middleware
app.use('/api', (req, res, next) => {
  // Only runs for paths starting with /api
  next();
});

app.get(path, ...handlers)

Register GET route handler.

app.get('/users', (req, res) => {
  res.json([{ id: 1, name: 'Alice' }]);
});

// With route parameters
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ id: userId });
});

// Multiple handlers
app.get('/complex',
  (req, res, next) => { /* validation */ next(); },
  (req, res) => { res.json({ result: 'ok' }); }
);

app.post(path, ...handlers)

Register POST route handler.

app.post('/users', (req, res) => {
  res.status(201).json({ created: true });
});

app.put(path, ...handlers)

Register PUT route handler.

app.put('/users/:id', (req, res) => {
  res.json({ updated: req.params.id });
});

app.delete(path, ...handlers)

Register DELETE route handler.

app.delete('/users/:id', (req, res) => {
  res.status(204).end();
});

app.patch(path, ...handlers)

Register PATCH route handler.

app.patch('/users/:id', (req, res) => {
  res.json({ patched: req.params.id });
});

app.all(path, ...handlers)

Register handler for all HTTP methods.

app.all('/webhook', (req, res) => {
  res.json({ method: req.method });
});

app.listen(port, host?, callback?)

Start listening for connections.

// Port only
app.listen(3000, () => {
  console.log('Server started');
});

// With host
app.listen(3000, '0.0.0.0', () => {
  console.log('Server started on all interfaces');
});

// Returns server info
const info = app.listen(3000);
console.log(info.backend); // 'io_uring', 'kqueue', 'iocp', or 'libuv'

app.close(callback?)

Stop the server.

app.close(() => {
  console.log('Server stopped');
});

app.onError(handler)

Register error handler middleware.

app.onError((err, req, res, next) => {
  res.status(500).json({
    error: err.message,
    stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
  });
});

Request Object

interface Request {
  method: string;           // HTTP method (GET, POST, etc.)
  path: string;             // URL path
  query: { [key: string]: string | string[] | undefined };  // Query parameters
  params: { [key: string]: string };  // Route parameters from path
  headers: { [header: string]: string | string[] | undefined };  // HTTP headers
  body?: unknown;           // Parsed request body
  rawBody?: Buffer;         // Raw body buffer
  ip?: string;              // Client IP address
}

Response Object

res.status(code)

Set HTTP status code. Returns this for chaining.

res.status(404).json({ error: 'Not found' });

res.json(body)

Send JSON response.

res.json({ status: 'success', data: [] });

res.send(body)

Send response (auto-detects content type).

res.send('Hello World');              // text/plain
res.send(Buffer.from('data'));        // application/octet-stream
res.send({ message: 'Hello' });       // application/json

res.set(name, value)

Set response header.

res.set('Content-Type', 'text/html');
res.set('X-Custom-Header', 'value');

res.set(headers)

Set multiple headers at once.

res.set({
  'Content-Type': 'application/json',
  'Cache-Control': 'no-cache'
});

res.get(name)

Get header value.

const contentType = res.get('Content-Type');

res.redirect(url, statusCode?)

Redirect to URL (default status: 302).

res.redirect('/new-path');
res.redirect('https://example.com', 301);

res.end(data?)

End response with optional final data.

res.end();
res.end('Final chunk');

Module Properties

const expresspro = require('express-pro');

console.log(expresspro.version);   // '1.0.0'
console.log(expresspro.platform);  // 'linux', 'darwin', 'win32'
console.log(expresspro.backend);   // 'io_uring', 'kqueue', 'iocp', 'libuv'

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | initialBufferSize | number | 16384 (16KB) | Initial buffer size for request/response handling. Increase for large headers or frequent large payloads. | | maxBodySize | number | 1048576 (1MB) | Maximum allowed body size in bytes. Requests with larger bodies will be rejected with 413 Payload Too Large. | | streamBody | boolean | false | Stream large bodies instead of buffering. Enable for file uploads or streaming APIs. See example below. |

When to Change initialBufferSize

Increase this value if:

  • You're sending large request headers (cookies, auth tokens)
  • Your average response body is >16KB
  • You see frequent buffer reallocations in profiling
// For APIs with large headers (JWT tokens, etc.)
const app = expresspro({
  initialBufferSize: 65536  // 64KB
});

When to Change maxBodySize

Increase this value if:

  • Accepting file uploads
  • Processing large JSON payloads
  • Building an upload API
// For file upload server
const app = expresspro({
  maxBodySize: 50 * 1024 * 1024  // 50MB
});

Note: Large maxBodySize values increase memory usage. Use streamBody: true for streaming large content.

When to Enable streamBody

Enable streaming if:

  • Handling file uploads
  • Proxying large responses
  • Processing data streams
  • Building a gateway/proxy
// For streaming/proxy use cases
const app = expresspro({
  streamBody: true,
  maxBodySize: 100 * 1024 * 1024  // Still needed for max protection
});

app.post('/upload', (req, res) => {
  // req.body is a stream when streamBody is true
  req.pipe(someWritableStream);
});

Platform Support

| Platform | Backend | Performance Tier | Requirements | |----------|---------|------------------|--------------| | Linux 5.1+ | io_uring | ★★★★★ Best | liburing-dev | | Linux <5.1 | libuv | ★★★☆☆ Good | None (fallback) | | macOS 10.14+ | kqueue | ★★★★☆ Excellent | None | | Windows 10+ | IOCP | ★★★☆☆ Good | None | | Other Unix | libuv | ★★★☆☆ Good | None (fallback) |

Backend Auto-Detection

Express-Pro automatically selects the best available backend:

  1. Linux with kernel 5.1+: Uses io_uring for maximum performance
  2. macOS: Uses kqueue for efficient event notification
  3. Windows: Uses IOCP for high-performance I/O
  4. Other platforms: Falls back to libuv (same as Node.js core)

Checking Your Backend

const app = expresspro();
console.log(expresspro.backend);  // 'io_uring', 'kqueue', 'iocp', or 'libuv'

Migrating from Express

Express-Pro is designed to be API-compatible with Express.js for common use cases.

What's Compatible

  • Route handlers: app.get(), app.post(), etc.
  • Middleware with next()
  • Request/response methods: res.json(), res.send(), res.status(), etc.
  • Route parameters: :id
  • Query string parsing

What's Different

| Feature | Express.js | Express-Pro | |---------|-----------|-------------| | Create app | const app = express() | const app = expresspro() | | Body parsing | Built-in middleware | Built-in (auto-parsed) | | Static files | express.static() | Not included (use nginx/CDN) | | View engine | Built-in | Not included (API-focused) | | Session | Built-in | Not included | | Cookie parsing | Built-in middleware | Not included |

See COMPATIBILITY.md for detailed migration guide.

Migration Example

Express.js:

const express = require('express');
const app = express();

app.use(express.json());

app.get('/api/users/:id', (req, res) => {
  res.json({ id: req.params.id });
});

app.listen(3000);

Express-Pro:

const expresspro = require('express-pro');
const app = expresspro();

// No need for express.json() - body parsing is built-in

app.get('/api/users/:id', (req, res) => {
  res.json({ id: req.params.id });
});

app.listen(3000);

Building from Source

Prerequisites

  • Node.js 18+ and npm 9+
  • Python 3.x (for node-gyp)
  • C/C++ compiler:
    • Linux: GCC 10+ or Clang 12+
    • macOS: Xcode Command Line Tools
    • Windows: Visual Studio Build Tools 2019+

Build Steps

# Clone the repository
git clone https://github.com/senapati484/express-pro.git
cd express-pro

# Install dependencies
npm install

# Configure build (optional, first time only)
npm run configure

# Build native addon
npm run build

# Run tests
npm test

# Run benchmarks
npm run bench

Troubleshooting

Linux: "uring.h not found"

# Install liburing development headers
sudo apt-get install liburing-dev  # Debian/Ubuntu
sudo dnf install liburing-devel    # Fedora/RHEL
sudo pacman -S liburing            # Arch

macOS: "xcode-select: error"

xcode-select --install

Windows: "MSBuild not found"

  • Install Visual Studio Build Tools with "Desktop development with C++" workload
  • Or run npm install --global windows-build-tools

Benchmarks

Run the benchmark suite:

# Full benchmark with autocannon (if installed)
npm run bench

# Regression test (CI-friendly)
npm run bench:regression

# Memory usage test
npm run test:memory

Expected Results

Results from AMD Ryzen 9 5900X, Node.js 20:

| Server | Requests/sec | Latency (p99) | |--------|-------------|---------------| | Express-Pro (io_uring) | 520,000 | 0.8ms | | Express-Pro (kqueue) | 155,000 | 2.1ms | | Express-Pro (IOCP) | 105,000 | 3.5ms | | Node.js http | 45,000 | 8.2ms | | Express.js | 18,000 | 22ms | | Fastify | 65,000 | 5.1ms |

Results may vary based on hardware, kernel version, and configuration.

Interpreting Results

The benchmark regression test (npm run bench:regression) compares against platform-specific thresholds:

  • Linux: Minimum 300,000 req/s
  • macOS: Minimum 80,000 req/s
  • Windows: Minimum 50,000 req/s

If your results are below these thresholds, check:

  1. CPU governor (Linux: performance mode recommended)
  2. Background processes consuming CPU
  3. Thermal throttling
  4. Debug build vs Release build

License

ISC License

Copyright (c) 2024 senapati484

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


Made with performance in mind. If you find Express-Pro useful, please consider starring the repository on GitHub!