Skip to main content

Command Palette

Search for a command to run...

Evaluating Node.js Express Alternatives in 2026: The Practical Case for DaloyJS

Updated
6 min read
Evaluating Node.js Express Alternatives in 2026: The Practical Case for DaloyJS
D
Devlin Duldulao is the creator of DaloyJS, a software engineer, educator, and published author with 10+ years of experience building and teaching modern web development. Originally from the Philippines and based in Norway since 2019, he writes books and courses for developers who want to ship real, secure systems — and takes his Asian home cooking about as seriously as his TypeScript.

Every few months someone on my team asks the same question: "we are starting a new service, do we just use Express again?" And every time, the honest answer has shifted a little further toward "no." Not because Express is broken, it runs half the internet, but because the list of things Express makes your problem has stopped being acceptable for a greenfield Node.js API in 2026.

This is a practical evaluation of DaloyJS (@daloyjs/core) as a Node.js Express alternative, written for engineers who have shipped enough Express to know exactly where it hurts. I will compare it honestly against the usual suspects (Fastify, Hono, Elysia) and tell you where it wins and where it does not.

The evaluation criteria

When I evaluate an Express alternative for a real team, I care about five things, in roughly this order:

  1. How much of the API contract is derived versus hand-maintained.

  2. What the security posture is by default, before anyone configures anything.

  3. Type safety from route to handler to client.

  4. Operational maturity: logging, shutdown, deploy targets.

  5. Supply-chain and dependency footprint.

Express scores poorly on 1 and 2, decently on 4, and leaves 3 and 5 entirely to you. Let me show how DaloyJS scores.

1. The contract is derived, not maintained

In Express, your route, your validation, your OpenAPI spec, and your client are four separate artifacts that you keep in sync by discipline alone. Discipline loses. DaloyJS makes one route definition the single source of truth:

import { App, NotFoundError } from "@daloyjs/core";
import { z } from "zod";

const Book = z.object({ id: z.string(), title: z.string(), author: z.string() });

app.route({
  method: "GET",
  path: "/books/:id",
  operationId: "getBookById",
  request: { params: z.object({ id: z.string() }) },
  responses: {
    200: { description: "Found", body: Book },
    404: { description: "Not found" },
  },
  handler: async ({ params }) => {
    const found = await db.books.find(params.id);
    if (!found) throw new NotFoundError(`No book ${params.id}`);
    return { status: 200, body: found };
  },
});

From this one object you get runtime validation, end-to-end types, an OpenAPI 3.1 document, and (via pnpm gen, which wraps Hey API) a typed fetch SDK your frontend imports directly. Rename a field, and the spec, the types, and the client all move with it, or refuse to compile. There is no openapi.yaml to forget.

This is the FastAPI ergonomic, brought to TypeScript. Fastify gets close with its JSON Schema + type providers, Elysia gets close with its typed handlers, but DaloyJS treats the OpenAPI document and the generated client as first-class outputs rather than bolt-ons. If "the docs are always right and the client is always typed" matters to you, this is the strongest story in the Node ecosystem right now.

2. The default security posture is the actual differentiator

Here is where most Express alternatives quietly punt. Be honest about the security checklist for an internet-facing HTTP API: body-size caps, request timeouts, prototype-pollution-safe parsing, CRLF/header-injection rejection, path-traversal defense, real 405s, 5xx redaction in production, JWT algorithm allowlists, constant-time credential comparison, SSRF guards on outbound fetches, secure headers, sane CORS, rate limiting.

Express ships almost none of that in core. Fastify ships some and leaves the rest to plugins. Hono and Elysia leave most of it opt-in. DaloyJS makes it the default, and the project's contributor rules explicitly treat weakening a guard to make a test pass as a bug. On by default or one line of first-party middleware away:

  • Streamed body read with a hard cap (1 MiB default), oversized Content-Length rejected before read.

  • requestTimeoutMs plus Node adapter headersTimeout / maxHeaderSize.

  • safeJsonParse strips __proto__ / constructor / prototype on every body, and the same reviver runs over JWT header and payload.

  • Header sanitization rejecting CRLF and NUL.

  • secureHeaders, requestId, rateLimit, JWT algorithm allowlists, timingSafeEqual credential checks, fetchGuard() SSRF defaults.

  • RFC 9457 problem+json errors with production redaction.

Why this matters in 2026 specifically: a growing share of backend code is written by AI agents, and an AI agent adds exactly the security you ask for and not one guard more. The Supabase and Aikido write-up on secure-by-default development put it well: "If you tell an AI to make something work, it might remove the very security checks that protect you." Starting from a framework where the checklist is the default flips the burden, you have to consciously remove protection rather than consciously remember to add it.

3. Types from route to handler to client

ctx.params, ctx.query, and ctx.body are typed from the schemas. Handlers return { status, body } and the body is checked per status. The generated client narrows results by status code. This is on par with Elysia's end-to-end typing and ahead of Express (which has none) and Fastify (which needs type providers and still does not generate a client for you).

4. Operational maturity

Structured logging, graceful shutdown, and a serve() adapter that sets the Node hardening knobs for you. The same app object runs on Node, Bun, Deno, Cloudflare Workers, and Vercel Edge, because the core speaks web-standard Request/Response. Express assumes a persistent Node http server, which is the wrong assumption for a lot of modern deploy targets. If "Node.js Express alternative" is your search term, note that this one is also a serverless and edge alternative without a rewrite.

5. Supply-chain footprint

@daloyjs/core has zero runtime dependencies. That is a real number, not marketing: fewer transitive packages is a smaller attack surface and faster, more auditable installs. Express pulls a tree; Fastify pulls a smaller but non-trivial one. For teams that have lived through a dependency-confusion or postinstall-script incident, this is not a footnote.

Where it does not win

Honesty section, because you should not trust a pitch without one:

  • Ecosystem size. Express has fifteen years of middleware for literally everything. DaloyJS does not. If you need a niche integration that exists only as Express middleware, you will be porting it.

  • Hiring familiarity. Every Node dev knows Express. DaloyJS is new, so onboarding has a small learning curve (the route-as-object and return-don't-mutate model).

  • Raw minimalism. If you genuinely want a bare router with nothing opinionated, Hono is lighter. DaloyJS is opinionated on purpose.

The verdict

For a new Node.js API in 2026 where you care about a correct OpenAPI contract, a typed client, and a security posture that does not depend on your memory, DaloyJS is the Express alternative I would pick, and the case gets stronger the more AI-written code lands in your repo. Fastify remains the safe, mature default; Hono wins on minimalism and edge; Elysia wins on Bun-native DX. DaloyJS wins on "the contract and the security checklist are the framework's job, not yours."

If you have an existing Express app and want the mechanics of moving it over, I wrote a companion field guide: migrating from Express to DaloyJS. This post is the evaluation; that one is the migration.

Docs and source: daloyjs.dev and github.com/daloyjs/daloy.