Module A-8·22 min read

Why Express middleware chains collapse under extreme throughput and how Fastify's Radix tree router with compiled JSON Schema achieves 3x gains.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module 7 — Routing Engines at Scale: Vanilla HTTP vs Radix Tree Frameworks

What this module covers: Your ingestion endpoint receives 50,000 requests per second. Before your code runs, the framework has already spent CPU time parsing the URL, finding the matching route, running middleware, and deserializing the body. At high throughput, this overhead is measurable — sometimes it is the difference between handling your load and dropping requests. This module covers why Express's linear middleware scan fails under extreme concurrency, how Fastify's Radix tree router achieves route matching whose cost depends on path length, not on the number of registered routes, and how compiled JSON Schema validation eliminates per-request interpretation overhead.


The Overhead Before Your Code Runs

For a payment gateway receiving a POST to /api/v2/payments/process, the framework must:

  1. Parse the URL (string split, decode percent-encoding)
  2. Find the matching route handler (scan routes or traverse a tree)
  3. Execute middleware chain (authentication, rate limiting, body parsing)
  4. Deserialize the request body (JSON.parse)
  5. Validate the payload (schema check)
  6. Hand control to your handler

At 100 req/sec, steps 1–5 cost microseconds and are invisible. At 50,000 req/sec, they cost milliseconds that compound into measurable throughput limits. The framework is not neutral — it has a throughput ceiling determined by its internal architecture.


Express: Linear Scan Middleware Chain

Express's routing model is a linked list of middleware functions. Every incoming request walks this list sequentially until a matching handler is found.

javascript

For a request to /api/v1/auth, Express checks: is this cors? Yes, run it. Is this helmet? Yes, run it. Is this json? Yes, parse the body. Is this rateLimiter? Yes, run it. Is the method POST and path /api/v1/auth? Yes — match.

The path-matching cost: Express uses path-to-regexp for route matching. For each route, it compiles the path pattern to a RegExp and tests the incoming URL against it. The test is O(N) in the number of routes.

With 200 routes and the matching route at position 180: every request triggers 180 RegExp tests. At 50,000 req/sec, that's 9 million RegExp executions per second — a measurable CPU load before any application logic runs.

javascript

Typical Express routing overhead on a 100-route app: 15–60μs per request. At 50K req/sec: 750ms–3s of CPU per second just in routing. That's 75–300% of a single CPU core dedicated to route matching.


Radix Tree Routing: O(m) Route Matching, Independent of Route Count

The hotel-concierge analogy: Express checks every name on the guest list at the door, one by one; Fastify's radix tree is a hotel concierge who reads your reservation code once and walks straight to your floor, your hallway, your room.

Fastify uses find-my-way — a Radix tree (compressed trie) router. Instead of scanning routes sequentially, it traverses a tree where common path prefixes are compressed into single nodes.

text

Matching /api/v2/payments/process:

  1. Does the URL start with /api/? Yes → descend
  2. Does the next segment start with v1 or v2? v2 → descend
  3. Does the next segment start with payments? Yes → descend
  4. Is the remainder /process? Yes → exact match → return handler

4 string prefix comparisons, regardless of the total number of routes. Adding 100 more routes to a different branch (/admin/...) does not change the cost of matching /api/v2/payments/process. The cost of matching is a function of the path's own length (segment count) — roughly O(m) where m is the number of path segments — and is effectively constant with respect to K, the number of registered routes. Route count does not appear in the cost at all, so it is not "logarithmic in K" — it simply doesn't depend on K.


Fastify: Architecture for Throughput

Fastify's design reflects a single principle: minimize overhead on the hot path.

JSON Schema Compilation via ajv

Every time Express parses and validates a request body at runtime, it interprets the validation logic dynamically. Fastify pre-compiles JSON Schema into optimized validator functions at startup using ajv:

javascript

What ajv compilation produces: instead of interpreting the schema on every request, ajv generates a JavaScript function like this:

javascript

fast-json-stringify: Compiled Response Serialization

Standard JSON.stringify is generic — it inspects every key and value at runtime to determine how to serialize them. fast-json-stringify pre-compiles a response schema into a serialization function:

javascript

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.