Skip to content
NestRS logo

NestRS

Scalable Rust backend apps with native performance. A Rust framework for native backend applications — ~25× throughput and ~20× less RAM than an equivalent Node service on the same hardware.

Native throughput

~463k req/s on 2 cores, ~213k per core, sub-millisecond p99, no GC pauses. The same hyper/tokio core as the fastest Rust web frameworks — with a structure on top.

An order of magnitude less RAM

~4 MB idle, ~6 MB under load — versus ~80–120 MB for an equivalent Node service. Smaller instances, higher density, a materially lighter cloud bill.

Boots in milliseconds

Each deployable is a static native binary with no runtime to warm up — autoscaling and cold starts stop hurting.

Types you don't fight

Rust types end to end — entity, DTO, route handler, dataloader, GraphQL schema, OpenAPI doc. No any, no unknown, no as casts at the boundaries, no runtime “undefined is not a function.”

Declarative, decorator-driven

#[module], #[controller], #[resolver], #[processor], #[gateway], #[cron_job], #[mcp]. Wiring is declarative — you write logic, not boilerplate.

Verified before it serves

The DI graph is checked at boot — a bad import fails startup with a clear error naming the missing wire. No reflection, no runtime “cannot resolve dependency” five minutes after deploy.

Secure & transactional by composition

Authn, authorization, row-level filtering, response masking, transaction scope — activated by importing a module, not by remembering to call them. Forgetting to redact a field becomes structurally hard.

Batteries included, opt-in by crate

HTTP, GraphQL, OpenAPI, WebSockets, Redis-backed queues, scheduling, an event bus, MCP, CASL-style authorization, health probes, OpenTelemetry — each an opt-in crate, so a worker compiles no HTTP stack at all.

The same “Hello World” service — a provider, a controller, a module — built once in NestRS and once in NestJS 11 on Node.js 20, under identical wrk load (2 cores, -t2 -c64 -d20s).

NestRS NestJS 11 · Node 20
Throughput 2 cores · req/s
NestRS ~463k
NestJS ~18k
~25×
Throughput per core · req/s
NestRS ~213k
NestJS ~17k
~13×
Latency p50 lower is better
NestRS 0.13 ms
NestJS 3.2 ms
~24×
Latency p99 lower is better
NestRS 0.57 ms
NestJS 6.4 ms
~11×
Memory idle lower is better
NestRS 4 MB
NestJS 80 MB
~20×
Memory under load lower is better
NestRS 6 MB
NestJS 118 MB
~18×

A minimal slice — a provider, a controller, and a #[module] that lists them. The DI graph is built and verified at boot; each app under apps/ compiles to its own native binary. For a full vertical slice (core port plus HTTP/GraphQL adapters), start with the tutorial.

apps/app/src/hello/service.rs
use nestrs_core::injectable;
#[injectable]
#[derive(Default)]
pub struct HelloService;
impl HelloService {
pub fn greeting(&self) -> &'static str { "Hello World" }
}
apps/app/src/hello/controller.rs
use std::sync::Arc;
use nestrs_http::{controller, routes};
use super::service::HelloService;
#[controller(path = "/")]
pub struct HelloController {
#[inject]
svc: Arc<HelloService>,
}
#[routes]
impl HelloController {
#[get("/")]
async fn hello(&self) -> &'static str {
self.svc.greeting()
}
}
apps/app/src/hello/module.rs
use nestrs_core::module;
use super::{controller::HelloController, service::HelloService};
#[module(providers = [HelloService, HelloController])]
pub struct HelloModule;
Terminal window
$ just dev app
2026-06-03T10:14:22.183Z INFO nestrs::http: bound 1 route on 0.0.0.0:3001
$ curl http://localhost:3001
Hello World

The same inject-and-decorate model carries every surface — HTTP, GraphQL, WebSockets, queues, scheduled jobs, MCP. Jump to a transport: HTTP, GraphQL, WebSockets, Data, Security.

NestRS is built for microservice-shaped backends without the old ceremony — several deployables, one shared feature library, and no obligation to split into many repositories while the team is still small.

Entities, services, and policy are written once. Each runnable has a clear responsibility — some sit on a public edge (surfaces clients and partners call), others stay non-public (background work, off the request path). Processes stay lean; your own services stay loosely coupled (shared contracts and data, not chatty RPC, no platform team or mesh required to get started).

shared featuresone product codebase — written once, composed into every deployablethe same model; different edges per responsibility
Public edgeexposed to clients and partners
  • API serviceREST · GraphQL
  • OAuth serviceOAuth2 · token issuance
Non-publicnot on the client request path
  • Workerqueues · background work

One monorepo, one feature library — who runs where; operational boundaries, not a rewrite of business logic.

Splitting by responsibility is only the first step. In production you scale horizontally per role — the same binary, more replicas when the pressure moves: API capacity follows demand, worker capacity follows queue depth. There is no single “scale the monolith” knob; each deployable gets its own replica count.

demand · trafficAPI replicas
queue · backlogWorker replicas

Issuers such as OAuth usually keep a small, steady footprint — scale where the load actually moves.

Alpha. The API still shifts, rough edges remain — NestRS is not production-ready yet. Stars and early feedback on Discussions shape what follows.