Stop Building 2025 Apps with 2010 Tools: Ditch Express, Learn HTTP/2

Kaan YagciKaan Yagci
5 min read

Most Node.js developers are still duct-taping Express.js to every project like it's 2010.

They’ll accuse you of “reinventing the wheel” if you mention using the native http module to build an HTTP server.

But here’s the reality:

Express isn’t the wheel, it’s a wrapper around the wheel.
The wheel is Node’s native http module. Express just adds weight, friction, and 2010-era assumptions.

In 2025, Express still doesn’t support HTTP/2. This is not just a missing feature. It's a result of Express’s architecture being tightly coupled to the legacy HTTP/1 request/response model.
It continues to encourage developers to build apps that are fundamentally limited to HTTP/1 behaviors unknowingly.
Meanwhile, Node.js has had a stable http2 module since v8.4.0 (2017). And unlike Express, HTTP/2 is broadly supported by all modern browsers, including Chrome (since 2015), Firefox (since 2015), Safari (since 2016), and Edge (since 2015), making it production-ready for nearly every user-facing application.

Let me repeat:
Node.js has supported HTTP/2 natively for over 7 years.
Express? Still dragging its feet.

The Real Problem: Developers Don't Understand the Platform

If you're using Express for basic routing and middleware in 2025, you're not building modern apps. You’re relying on abstractions instead of understanding how the platform works.

Most developers using Express don’t even know how to build a basic HTTP/1 server with Node's native http module.

Here’s what that actually looks like:

import http from 'node:http';

const server = http.createServer((req, res) => {
  if (req.url === '/' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from native HTTP');
  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(3000);

When you show this to most Node.js developers, they’re genuinely surprised at how simple it is.

Many even say:

"That looks like Go."

And they’re not wrong, Go is known for its simplicity by design.
Node.js also gives you the same low-level control and simplicity if you read the docs.

And no, wrapping an Express app with an HTTP/2-compatible server doesn’t fix anything.
You’re still funneling requests through a layer that doesn’t speak the protocol natively.

Why HTTP/2 Actually Matters

Let’s get into why HTTP/2 isn’t just a buzzword, it's a massive technical leap over HTTP/1.1:

FeatureHTTP/1.1HTTP/2
Request MultiplexingOne request per connectionMultiple concurrent requests
Binary ProtocolText-based, verboseCompact binary frames
Header CompressionRepeated headersHPACK compression
Server PushNot supportedPush resources before a request
TLS UsageOptionalEffectively required

What does this mean for developers and products?

  • Faster page loads due to parallel asset delivery

  • Reduced latency, especially on mobile networks

  • Smarter caching and resource management

  • Cleaner architecture with fewer bundling hacks

If you’re building a product that prioritizes performance or mobile UX and you’re still stuck on HTTP/1 via Express… you’re not just missing out, you’re holding your product and your users back.

Building a Native HTTP/2 Server in Node.js

Before you think this is too complicated or low-level, here's a minimal HTTP/2 server using just native Node.js, no frameworks, no wrappers. It's surprisingly clean:

import { createSecureServer } from 'node:http2';
import { readFileSync } from 'node:fs';

const server = createSecureServer({
  key: readFileSync('./localhost-key.pem'),
  cert: readFileSync('./localhost-cert.pem'),
});

server.on('stream', (stream, headers) => {
  const path = headers[':path'];
  if (path === '/') {
    stream.respond({ 'content-type': 'text/html', ':status': 200 });
    stream.end('<h1>Hello over HTTP/2</h1>');
  } else {
    stream.respond({ ':status': 404 });
    stream.end('Not found');
  }
});

server.listen(8443);

Converting Express Routes to Native HTTP/2

If you're convinced HTTP/2 is the way forward, and you're ready to ditch Express, let’s look at how easy it is to convert your routes.

  1. Basic GET route

  • Express:

      app.get('/hello', (req, res) => {
        res.send('Hello World');
      });
    
  • HTTP/2:

      if (method === 'GET' && path === '/hello') {
        stream.respond({ ':status': 200, 'content-type': 'text/plain' });
        stream.end('Hello World');
      }
    
  1. JSON API route

  • Express:

      app.get('/api/data', (req, res) => {
        res.json({ message: 'Hello JSON' });
      });
    
  • HTTP/2:

      if (method === 'GET' && path === '/api/data') {
        stream.respond({ ':status': 200, 'content-type': 'application/json' });
        stream.end(JSON.stringify({ message: 'Hello JSON' }));
      }
    
  1. Static file serving

  • Express:

      app.use(express.static('public'));
    
  • HTTP/2:

      import path from 'node:path';
      if (method === 'GET' && path === '/') {
        stream.respondWithFile(path.join(__dirname, 'public/index.html'), {
          'content-type': 'text/html'
        });
      }
    
  1. Middleware: logging

  • Express:

      app.use((req, res, next) => {
        console.log(`${req.method} ${req.url}`);
        next();
      });
    
  • HTTP/2:

      server.on('stream', (stream, headers) => {
        const method = headers[':method'];
        const path = headers[':path'];
        console.log(`${method} ${path}`);
        // ... handle routes here
      });
    

    Final Thoughts

  • Express.js is stuck in HTTP/1.1 and won't catch up.

  • Native HTTP/2 in Node.js has been ready since 2017 — you have no excuse.

  • HTTP/2 gives you real-world performance wins: multiplexing, binary frames, and smarter delivery.

  • Most apps don’t need frameworks — they need developers who understand the stack.

  • Learn your tools. Ditch abstractions that hold you back. Stop shipping legacy.

You’re not building “modern” apps if you’re using outdated tools to fake modernity..

Learn the platform. Stop chasing the hype. Leave 2010 behind.


Need help modernizing your Node.js stack or ditching Express for good?
I consult with teams to build secure, fast, future-proof backends using native features, not legacy wrappers.

DM me. No fluff, just real engineering.

2
Subscribe to my newsletter

Read articles from Kaan Yagci directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kaan Yagci
Kaan Yagci

Senior Platform Engineer. Infra and programming languages nerd. I write about the stuff nobody teaches: how things really work under the hood, containers, orchestration, authentication, scaling, debugging, and what actually matters when you’re building and running real systems. I share what I wish more real seniors did: the brutal, unfiltered truth about building secure and reliable systems in production.