All Posts
EngineeringMay 15, 20267 min read

Why We Built Ingenium: A Modern Version of Express That Scales Better

Express is still the default for a reason. It's also showing its age. We wanted a modern version that scales, without forcing teams off the mental model they already have.

We built Ingenium for a simple reason. Express is still the default for a reason, the mental model is good, the ecosystem is enormous, and most Node.js engineers can read an Express handler at a glance. It's also showing its age in ways that matter under load. We wanted a modern version that scales better, without throwing out the parts of Express that actually got things right.

That's the whole pitch. The rest of this post is what "modern" and "scales better" mean in practice, and what we decided to keep, change, or throw out.

What's Still Right About Express

It's worth starting here, because almost every "Express replacement" framework starts by listing what Express got wrong and ends up replacing things that were fine. Express got several things right that newer frameworks regularly get worse:

  • The handler signature is teachable. (req, res, next) is three things, in an order you remember after one example.
  • The middleware model is composable. Anything that touches a request can be expressed as a function that takes the same shape and decides whether to continue.
  • The ecosystem is real. Body parsing, sessions, CSRF, file uploads, every cloud provider's SDK, every auth library, all of it works because the contract has been stable for a decade.

A modern Express has to preserve those things. If the price of better performance is rewriting how every handler is shaped, the framework isn't a modern Express, it's a different framework with a familiar logo.

What Express Actually Costs

Express's structural weaknesses are not a mystery. They're three specific things, and they compound:

  • Linear routing. Express scans its route table top to bottom for every request. At 50 routes this is invisible. At 400 routes with regex matching in the middle of the table, it's measurable. At 1,200 routes with nested routers, it dominates the request budget.
  • Untyped req and res. The handler signature gives you nothing. Body shape, query params, route params, and locals all live in any until something runtime validates them. Most teams bolt on Zod or class validator and call it solved. It's solved at the validation boundary. It's not solved in the 80 percent of code that runs after the boundary, where contributors quietly drift the request shape and integration bugs accumulate.
  • Per request allocation. Every request allocates a new req object, a new res object, a new middleware chain closure stack, and whatever your middleware adds on top. Under sustained load this turns into GC pressure that doesn't show up in any single trace but shapes the entire p99 curve.

None of these are bugs. They're consequences of decisions made when Express was new and JavaScript runtimes were different. They're also why every benchmark Express loses, it loses for the same three reasons.

Why We Built Instead of Adopted

Hono is excellent. Fastify is excellent. If you're starting fresh, either is a defensible choice. The reason neither one was what we wanted is that adopting them means leaving Express, and leaving Express is more expensive than the benchmarks make it look.

The cost of switching frameworks breaks down into three buckets, and only the first one is obvious:

  1. Rewriting handlers. Different signature, different return semantics, different error model. This is the visible cost and the one teams budget for.
  2. Rewriting middleware. Every piece of custom middleware in an established codebase has to be ported. The framework's middleware contract is different. Order of execution is different. What next() means is different.
  3. Rewriting institutional knowledge. The on call engineer who debugged a request lifecycle bug at 2am six months ago now has to relearn the lifecycle. Every runbook, every postmortem reference, every "this is how requests flow through our system" diagram becomes stale on the same day.

The third bucket is the one that kills migrations. The first two have estimates. The third one is invisible until it isn't.

Ingenium attacks the first two costs by being Express shaped. Handlers look like Express handlers, plus a return value. Middleware looks like Express middleware. req, res, next exist. The institutional knowledge mostly carries over because the lifecycle mostly carries over. We weren't trying to invent a new way to write HTTP servers. We were trying to keep the way Node engineers already write HTTP servers and fix what was actually slow.

What's Different Under the Hood

The site goes deeper on the implementation. The short version:

Radix trie with wildcard backtracking replaces the linear scan. Route lookup becomes O(length of path) instead of O(number of routes). The trie supports wildcards and param segments without falling back to regex on the hot path. On a 1,200 route table this changes the routing cost from "noticeable in flame graphs" to "rounding error."

Strict, Express shaped typed context replaces untyped req and res. The context object has the methods you expect (ctx.body, ctx.query, ctx.params, ctx.state, ctx.json(), ctx.send()), with full inference end to end. Route definitions carry schema, schema flows into handler types, handler return types flow into response types. The drift surface that used to live in the 80 percent of code after the validation boundary collapses.

Pooled contexts with lazy getters replace per request allocation. The context object is reused from a pool. Properties that are expensive to parse (body, signed cookies, JWT claims) are computed on first access, not on every request. Routes that don't read the body don't pay for body parsing. This is where the throughput gap to Hono and Fastify closes.

Handlers return values. You return a string, an object, a Response, or anything serializable. Ingenium handles the wire format. The res.json() ceremony is optional. This is small but it changes how handlers read at scale.

Body parsing is lazy. Always on body parsing is one of those Express defaults that nobody questions and that costs every request, including the ones that never touch the body. In Ingenium, the body is parsed when you ask for it. Health checks, redirects, and read endpoints get the parse cost they actually need, which is zero.

The Production Hardening

A framework that wins synthetic benchmarks and loses to a single malformed header in production is not useful. The hardening features are opt in, but the opt in surface is one line each:

  • Request timeouts with proper cleanup
  • Body size caps before parsing, not after
  • Header injection guards on response writes
  • JWT validation with JWKS rotation
  • Idempotency keys with pluggable storage
  • CSRF protection that doesn't break SPAs
  • Signed sessions with rotation

Each of these is middleware most teams end up writing or reaching for anyway. Consolidating them into the framework, with consistent configuration and consistent failure modes, was the second half of why this project made sense.

How It Mounts

Ingenium runs inside an existing Express app as a router. You don't have to rewrite anything to try it. You point one path at an Ingenium router, you keep the rest of the app exactly as it is, and you measure. If the hot path gets faster, you move more routes. If it doesn't, you've lost a half day, not a quarter.

That property was deliberate. The point of a modern Express isn't to make people throw their Express app away. It's to give them a way to fix the parts that are actually slow without touching the parts that are fine.

Why We Built This

This started as something we wanted to exist. Express is the framework most Node.js engineers, including ours, learned the language on. It still has the cleanest mental model for HTTP in the ecosystem. The fact that it's slower than it should be, and untyped in places that matter, has been true for years, and the answer the community kept giving was "use a different framework." That's a real answer. It's just not the only one.

A modern version of Express that scales is the answer we wanted on the shelf. Building it ourselves was the shortest path to having it.

The framework lives at ingenium.contracollective.com. If you're running into the parts of Express that don't scale and the migration cost to something else doesn't pencil, that's the gap it was built for.

[ 02 ] — Keep Reading

More from the lab.

Jun 14, 2026Engineering

Stytch vs Magic.link: Passwordless Authentication for Modern Web Apps

Passwords are a UX tax. Every password a user creates is a support ticket waiting to happen, a security incident in the making, and a checkout abandonment rate line item your e-commerce analytics will eventually surface. The industry has known this for years. Passwordless authentication, once a niche experiment, is now table stakes for consumer-facing applications that care about conversion.

Jun 12, 2026Engineering

Cognito vs Clerk: AWS Native Auth vs Developer-First Identity in 2026

AWS Cognito is one of the most widely used authentication services in the world, and one of the most frequently replaced. Its usage stats reflect the gravitational pull of the AWS ecosystem. Its replacement frequency reflects something more honest about its developer experience. Clerk built its entire company on the premise that authentication should feel like a first-party framework feature, not a cloud service you configure through a JSON policy document.

Jun 12, 2026Engineering

Shopify Plus vs Salesforce Commerce Cloud: 2026 Enterprise Platform Decision

The enterprise commerce platform market has bifurcated sharply. On one side: Salesforce Commerce Cloud, a legacy powerhouse built for complexity and customization at a price that reflects it. On the other: Shopify Plus, a platform that has spent the last four years systematically closing the enterprise feature gap while keeping total cost of ownership radically lower. The question for most brands in 2026 is no longer whether Shopify Plus is enterprise-ready. It is whether SFCC's remaining advantages justify its cost.

Ready when you are

Want to discuss this topic?

Start a Conversation