Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Ahmed Sozzer could use Express, but he could not explain what happened to a request between arriving and getting a response. His answer was to build PlusWeb, an Express-style web framework in C++, and to implement middleware chaining, next(), handler order, error handling and routing himself. The lesson he reports is that writing the mechanism made its behavior visible. Rebuilding every layer underneath it, though, pulled him toward performance work that was not the original goal.

Why he started over in C++

The project began as a learning exercise focused on middleware chaining. Sozzer’s first attempt was written in JavaScript, but he found it sat at too similar an abstraction level to Express to teach him much. Restarting in C++ forced him to deal with the parts Express hides: sockets, parsing, memory and the event loop. That friction is the reason the project taught him anything.

How the routing differs

According to the article, Express matches a request by scanning its layer stack in registration order. PlusWeb instead walks the URL segment by segment through a trie keyed on method and path. Sozzer’s claim is that lookup cost in his design depends on the number of path segments rather than the total number of routes. That is a description of his implementation, not an independent analysis of Express internals.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Aspect Express (as the author describes it) PlusWeb (the author’s implementation)
Lookup structure Ordered layer stack, checked in registration order Segment trie keyed on method and path
What drives lookup cost How many layers are checked before a match Number of path segments in the request
Where it helps you learn Middleware order is visible in code, but the matching loop is hidden inside the library The matching logic is small enough to read end to end

What the benchmarks show, and what they do not

Sozzer reports throughput measurements for both frameworks at three route counts. The setup, as he states it, pinned the process to one core and used identical handlers and payloads. These are his measurements, published in a 2026 DEV Community post originally published at amsozzer.com. They have not been independently reproduced.

Routes PlusWeb (requests per second) Express (requests per second) Multiple reported by the author
5 91,950 19,236 4.8×
1,000 90,085 5,639 16×
10,000 89,636 355 253×

Sozzer calls the five-route row the honest one for a typical small application, and he suggests quoting 4.8× if you need a single figure. The large multiples at 1,000 and 10,000 routes come mainly from Express’s throughput falling as the route count rises. PlusWeb’s figures stay roughly flat across all three rows, so the gap is not evidence that the C++ version is simply faster at every size. Treat the 16× and 253× rows as a statement about route-table scaling in this one test, not as a general verdict on Express against C++ frameworks.

Replacing the hand-built networking layer

The early server used a blocking, hand-built loop. Sozzer replaced it with libuv for the event loop and with llhttp for HTTP parsing, in place of his own parser. He presents the parser change as a correctness fix as well as an implementation choice: the custom version mishandled several message-framing cases that llhttp covers.

Profiling found a cost in the response path

The most useful engineering lesson in the article comes from profiling. The status-code map was being rebuilt on every response. Moving it to shared static storage removed the repeated allocations and insertions. Sozzer’s comparison ran each version 200,000 times with the same compiler flags and produced byte-identical output.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Measurement Before After Reported change
HttpResponse construction 3,390 ns 10.0 ns 339×
Full response path 3,400 ns 255 ns 13×

The gap between those two rows is the useful part. Construction got about 339 times faster, but the full path improved about 13 times, because the rest of the response work was still there.

Where the time actually goes

Sozzer’s profile of his own setup shows where the time is spent. Most of it is not in the framework code at all.

Component Share of profile (author-reported)
libc syscall stubs (send/recv) About 71%
llhttp internals 3.0%
Message completion 1.8%
Response serialization 0.5%
Router lookup 0.5%

These shares describe one machine and one workload. They are not expected values for other hardware or applications. What carries over is the method: measure the hot path before assuming the most visible subsystem is the bottleneck. After the router optimization, lookup accounted for only 0.5% of the profile.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What the author concludes

Sozzer is clear that the purpose was understanding, not winning benchmarks. He writes, “That was the point. The benchmarks are a side effect, and a slightly misleading one, because they make the project look like it was about speed.” He also says that because he wrote the code that handles a request, he can explain what Express does when one arrives.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The article does not establish that PlusWeb is ready for production, that it matches Express feature for feature, or that its benchmark results will reproduce on other machines. It is a learning project with a public codebase.

Best Value

Looking at PlusWeb yourself

  • License: the article states that PlusWeb is on GitHub under the MIT license.
  • Router playground: the article says a playground runs the router compiled to WebAssembly, which lets you test route matching without building the C++ project.
  • Current status: the article does not establish the repository’s current state beyond its own statements, so check the repository directly before relying on any detail.

If you are learning how Express works, the most transferable exercise is the one Sozzer describes: write a small middleware runner and a router, then check its behavior against Express using the same request sequence. You will learn more from the mismatches than from the speed numbers.

For a developer, the article’s best takeaway is methodological. Building the mechanism clarified its behavior, and profiling showed that the visible parts of a framework are not always the expensive ones.

Source: Ahmed Sozzer, “I could not understand Express, so I wrote my own,” DEV Community (displayed September 23, 2026), originally published at amsozzer.com.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Sozzer’s author reported figures are not independently validated.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.