AponiaJS vs NestJS
NestJS is a mature, platform-agnostic Node framework with a complete request pipeline. AponiaJS reuses its vocabulary on Bun with a much smaller feature set.
NestJS is the reference point for this project, so the honest comparison is mostly a list of what NestJS has and AponiaJS does not.
At a glance
Runtime
Partial. Bun only
Yes. Node, and Bun in practice
HTTP platform
Partial. Elysia only
Yes. Express or Fastify adapter
Maturity
No. Alpha, API changes between releases
Yes. Stable, years of production use
Modules and imports
Yes. Implemented
Yes. Implemented
Constructor injection
Partial. Implemented, singleton only
Yes. Request and transient scopes too
Controllers and decorators
Yes. All seven methods, whole and named parameters
Yes. Implemented
Validation
Yes. Route schemas and @Validation() models
Yes. ValidationPipe with class-validator
Guards, interceptors, pipes, filters
No. Not implemented
Yes. Implemented
Lifecycle hooks
No. Not implemented
Yes. OnModuleInit, OnApplicationShutdown, others
Testing module and overrides
No. Not implemented
Yes. Implemented
OpenAPI, microservices, GraphQL, queues
No. Not implemented
Yes. First-party packages
Typed HTTP client
Partial. Eden Treaty from native routes
Partial. Generated from OpenAPI, or manual
The code looks familiar
import { Body, Controller, Get, Injectable, Module, Param, Post } from "@aponiajs/common";
import { AponiaFactory } from "@aponiajs/platform-elysia";
@Injectable()
class UserService {
findOne(id: string) {
return { id };
}
}
@Controller("users")
class UserController {
constructor(private readonly users: UserService) {}
@Get(":id")
findOne(@Param("id") id: string) {
return this.users.findOne(id);
}
}
@Module({ controllers: [UserController], providers: [UserService] })
class AppModule {}
const app = await AponiaFactory.create(AppModule);
await app.listen(3000);Anyone who has written NestJS can read that. The differences start one layer down.
@Injectable() carries less meaning
In AponiaJS the decorator exists so TypeScript emits constructor parameter types for the container. It does not attach scope metadata, because there are no scopes — every provider is a singleton constructed once at startup. See providers.
Validation is a schema, not a pipe
There is no ValidationPipe, no class-validator, and no
class-transformer. A schema goes on the route decorator and a rejected
request is answered before the handler runs:
const createUser = { body: z.object({ name: z.string().min(2) }) };
@Post("/", createUser)
create(@Body() body: z.infer<(typeof createUser)["body"]>) {
return body;
}Any Standard Schema validator works — Zod,
ArkType, Valibot — alongside TypeBox and Elysia's t. Details in
validation.
There is no request pipeline to hook into
This is the largest gap. NestJS gives you four extension points around a handler; AponiaJS gives you none of them yet. Cross-cutting behaviour is written as Elysia hooks instead, through native access or a plugin module. That works, but it is Elysia's model, not Nest's, and it does not participate in the module graph.
Errors are Problem Details
httpErrors.notFound("...") produces an RFC 9457 body with type, title,
status, and detail. NestJS produces its own shape from HttpException.
See errors.
Which one to pick
Choose NestJS when
- you are shipping to production;
- you need guards, interceptors, pipes, or exception filters;
- you deploy to Node, or to a platform that does not run Bun;
- you want OpenAPI documents generated from decorators;
- you need microservices, GraphQL, queues, scheduling, or caching packages;
- you want a testing module with provider overrides;
- you are hiring, and Nest experience is a common line on a CV.
Choose AponiaJS when
- Bun is already the runtime and Elysia is already the server;
- module boundaries and constructor injection are what you miss from Nest, not the request pipeline;
- you want Eden Treaty end-to-end types rather than a generated OpenAPI client;
- alpha software is acceptable for this codebase.
Porting an existing Nest application
From NestJS has the concept-by-concept mapping, and current limitations lists every runtime feature that is still missing.
Frequently asked questions
- Can I run NestJS on Bun instead of using AponiaJS?
- Often yes. NestJS runs on Bun for many applications, and if your code depends on guards, interceptors, exception filters, provider scopes, or the testing module, that is the right path — AponiaJS does not implement any of them. AponiaJS is worth considering when you want the Elysia request engine and Eden Treaty types underneath a Nest-shaped codebase.
- Is AponiaJS a fork of NestJS?
- No. It is an independent implementation that borrows naming so the concepts transfer. There is no shared code, no platform adapter abstraction, and no compatibility guarantee with Nest packages.
- Do NestJS decorators work in AponiaJS?
- The names match but the packages do not. Import decorators from "@aponiajs/common" and the factory from "@aponiajs/platform-elysia". Nest packages such as @nestjs/common are not compatible.
Compare frameworks
How AponiaJS compares to NestJS, AdonisJS, Elysia, Express, Fastify, and Hono — architecture, runtime, validation, and what each one is good at.
AponiaJS vs AdonisJS
AdonisJS is a batteries-included full-stack Node framework with an ORM, auth, and validation. AponiaJS is an HTTP and dependency injection layer on Bun, and nothing more.