AponiaJS vs Express
Express decides almost nothing and has the largest middleware ecosystem in Node. AponiaJS decides how the application is structured and runs only on Bun.
Express is the baseline the rest of the Node ecosystem is measured against. It is small, stable, unopinionated, and has more middleware written for it than every other framework here combined.
At a glance
Runtime
Partial. Bun only
Yes. Node, and Bun
Age and stability
No. Alpha
Yes. The most widely deployed Node framework
TypeScript
Yes. Written in TypeScript, types first-class
Partial. Types come from @types/express
Structure
Yes. Modules, controllers, providers
No. Whatever you build
Dependency injection
Yes. Constructor injection
No. None
Validation
Yes. Route schemas, rejected before the handler
Partial. Middleware you choose
Error format
Yes. RFC 9457 Problem Details
Partial. Your error handler
Middleware ecosystem
No. Elysia plugins, small
Yes. Enormous
Express gives you a chain
import express from "express";
const app = express();
app.use(express.json());
app.get("/users/:id", (req, res) => {
res.json({ id: req.params.id });
});
app.listen(3000);Everything after that — where handlers live, how services are constructed, how input is validated, what an error body looks like — is a decision your team makes and re-litigates. That freedom is why Express is still everywhere, and why two Express codebases rarely look alike.
AponiaJS gives you a shape
import { Controller, Get, Injectable, Module, Param } from "@aponiajs/common";
import { AponiaFactory } from "@aponiajs/platform-elysia";
@Injectable()
class UserService {
find(id: string) {
return { id };
}
}
@Controller("users")
class UserController {
constructor(private readonly users: UserService) {}
@Get(":id")
find(@Param("id") id: string) {
return this.users.find(id);
}
}
@Module({ controllers: [UserController], providers: [UserService] })
class AppModule {}
await (await AponiaFactory.create(AppModule)).listen(3000);The decisions Express leaves open are made here: modules own boundaries, providers own construction, validation rejects bad input before the handler, and errors answers with a single documented format.
The honest trade
Ecosystem. This is not close. Passport, Multer, and thousands of other packages assume Express request and response objects and cannot be reused. Whatever middleware you rely on, budget for replacing it with an Elysia plugin or writing it yourself.
Middleware model. Express middleware is the extension point for everything. AponiaJS does not implement middleware, guards, or interceptors — cross-cutting behaviour is an Elysia hook, added through native access or a plugin module.
Risk. Express has a decade of production behind it and a stable major release. AponiaJS is alpha.
Which one to pick
Choose Express when
- you deploy to Node, or portability matters more than throughput;
- specific Express middleware is load-bearing in your application;
- the team wants the smallest possible framework surface;
- the service is small enough that structure is not the problem;
- you are shipping to production now.
Choose AponiaJS when
- Bun is the runtime and Web standard
Request/Responseis fine; - you want typed validation and a documented error format without assembling them;
- the codebase is large enough that "where does this go" is a recurring question;
- alpha software is acceptable for this codebase.
Coming from Express by way of Nest
If Express plus a homegrown structure is what you have, the NestJS comparison is likely more useful — it covers the same class model with a production-ready implementation.
Frequently asked questions
- Is AponiaJS faster than Express?
- An AponiaJS application is an Elysia application on Bun, and that stack is designed for higher throughput than Express on Node. A ratio without a workload attached is not worth much, though — the benchmark section publishes the harness, pinned versions, and phases so the number can be checked.
- Can I use Express middleware with AponiaJS?
- No. Express middleware expects Express request and response objects. AponiaJS runs on Elysia, which uses Web standard Request and Response, so you need Elysia plugins or your own hooks instead.
- Does Express run on Bun?
- Yes, Bun implements enough of Node for Express to work. Running Express on Bun is a legitimate option and keeps the middleware ecosystem; it just does not give you Elysia's routing or typing.
AponiaJS vs Elysia
Elysia is the runtime AponiaJS is built on. This page is about what the module graph adds, what it costs, and when the plain chained application is still the better answer.
AponiaJS vs Fastify
Fastify organises applications with encapsulated plugins and JSON Schema validation. AponiaJS organises them with a validated module graph and constructor injection on Bun.