Architecture

Framework Comparison

Side-by-side code comparison of NextRush, Express, Fastify, Hono, and Koa — routing, middleware, error handling, and TypeScript support.

How NextRush compares to popular Node.js frameworks — not only speed, but how you write code.

Looking for benchmarks?

This page compares code patterns and architecture. For raw performance numbers, see Benchmarks.

At a Glance

FeatureNextRushExpressFastifyHonoKoa
TypeScriptFirst-class (strict)Bolt-on (@types)Built-inBuilt-inBolt-on (@types)
Runtime deps03115024
Multi-runtimeNode, Bun, Deno, EdgeNode onlyNode onlyNode, Bun, Deno, EdgeNode only
Context APISingle ctx objectreq + res + nextrequest + replySingle c objectSingle ctx object
Middleware modelKoa-style onionLinear chainHooks + lifecycleKoa-style onionOnion model
Built-in DIYes (@nextrush/di)NoNoNoNo
DecoratorsYes (@Controller, @Get)NoVia pluginsNoNo
ExtensibilityExtension + middlewareapp.use()Encapsulated pluginsMiddleware onlyapp.use()
RoutingSegment trie (O(k))Linear scan (O(n))Radix tree (O(k))Radix tree (O(k))Via koa-router

NextRush's extensibility model is layered: app.use() middleware for the vast majority of cases, plain-function registrars (e.g. registerControllers) for wiring subsystems, and the rare, long-lived Extension (via app.extend() + await app.ready()) for app-scoped services like an event bus. There is no Plugin interface or plugin registration API.


Hello World

The same endpoint in every framework.

src/index.ts
import { createApp, createRouter, listen } from 'nextrush';

const app = createApp();
const router = createRouter();

router.get('/', (ctx) => ctx.json({ message: 'Hello World' }));
app.route('/', router);
await listen(app, 8080);

Middleware

How each framework composes middleware — logging, auth, and error handling.

Koa-style onion model. Code before ctx.next() runs on the way in, code after runs on the way out.

// Timing middleware
app.use(async (ctx) => {
  const start = Date.now();
  await ctx.next();
  ctx.set('X-Response-Time', `${Date.now() - start}ms`);
});

// Auth middleware
app.use(async (ctx) => {
  const token = ctx.get('authorization');
  if (!token) throw new UnauthorizedError('Missing token');
  ctx.state.user = verifyToken(token);
  await ctx.next();
});

Key difference: NextRush and Koa share the onion model — you write both "before" and "after" logic in one function. Express uses linear chains with separate error middleware. Fastify uses lifecycle hooks.


Error Handling

Typed error classes with automatic status codes. Thrown errors become JSON responses.

import { NotFoundError, ValidationError } from '@nextrush/errors';

router.get('/users/:id', (ctx) => {
  const user = db.find(ctx.params.id);
  if (!user) throw new NotFoundError('User not found');
  ctx.json(user);
});

// Custom error handler
app.setErrorHandler((error, ctx) => {
  ctx.status = error.status ?? 500;
  ctx.json({
    error: error.message,
    code: error.code,
  });
});

TypeScript Support

AspectNextRushExpressFastify
Source languageTypeScriptJavaScriptTypeScript
Types includedYes (strict mode)No — install @types/expressYes
Route param inferenceVia generics on ctxManual casting requiredVia JSON Schema
Body type safetyTransform decorators (Zod, etc.)None built-inJSON Schema validation
Strict modeEnforced — zero anyOptionalOptional
// NextRush — types flow naturally
router.get('/users/:id', (ctx) => {
  const id = ctx.params.id; // string (typed)
  const page = ctx.query.page; // string | undefined (typed)
  ctx.json({ id, page }); // return type checked
});

When to Choose What

Your priorityLikely fitNotes
Raw throughput (Node.js only)FastifyAOT JSON serialization, mature radix tree
Multi-runtime (Bun, Deno, Edge)NextRush or HonoCompare adapters and deploy targets
Strict TypeScript + small core depsNextRushCore packages avoid extra runtime dependencies
Large ecosystem + communityExpressBroad middleware ecosystem and tutorials
Class-based + DINextRushOptional decorators and DI in the same stack
Minimal learning curveKoa or ExpressFamiliar patterns and documentation
Mixed functional + class routesNextRushBoth styles can coexist in one app

Migration Paths

Ready to switch? Follow the step-by-step guides:

Was this helpful?

On this page