Fast & minimalist
REST framework for Node.js

Blazing fast, tiny, and secure-by-default. Express-inspired API with serverless support, nested routers, and zero bloat.

7
HTTP methods
v6.1
latest
Node 24+
runtime
3
dependencies
TS
types built-in

Safer APIs, clearer operations

Restana 6.1 strengthens production behavior without trading away routing performance.

Reliable lifecycle

service.start() now rejects cleanly on socket and port conflicts, making startup failures observable and recoverable.

Explicit trust

Error details are opt-in for local debugging, while forwarded TLS headers require an explicitly trusted proxy.

Stronger API contracts

Boolean bodies, array-valued headers, cache disabling, and TypeScript declarations now match documented behavior.

Performance guarded

Response and routing benchmarks now run with CI budgets, including a direct router-integration overhead check.

Why restana?

A framework designed for speed, simplicity, and production safety.

Blazing Fast

Lightweight routing with minimal overhead. The sequential router uses internal caching for repeated lookups — tuned for raw throughput.

🛡

Secure by Default

Default error masking, header injection protection, security headers, TRACE disabled, and isolated config snapshots — all on by default.

🔗

Middleware Engine

Express-compatible middleware with full async/await support. Global, prefix, and route-level — you choose the scope.

🧩

Nested Routers

Modular architecture with nested routers via service.newRouter(). Mount under prefixes and compose cleanly.

☁️

Serverless Ready

Native integration with AWS Lambda via serverless-http and Google Cloud Functions for Firebase. Deploy anywhere.

📦

Minimal Footprint

Three runtime dependencies. Zero bloat. The res.send() method handles null, strings, buffers, objects, streams, and promises — all in one call.

Safe Out of the Box

restana v6.1 ships with hardened security defaults. No extra packages needed.

🔒

Safe Error Masking

Error details are hidden in every environment by default. Local development can explicitly opt in with debugErrors: true; production always masks details.

🚫

Header Injection Protection

Security-sensitive and hop-by-hop headers (transfer-encoding, content-length, connection, set-cookie, etc.) are silently dropped from res.send(). Invalid header characters are caught, not crashed.

🛡

Default Security Headers

Every response gets X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and X-XSS-Protection: 0. HSTS is set for direct TLS or explicitly trusted proxies.

🔐

TRACE Disabled by Default

Eliminates Cross-Site Tracing (XST) attack surface. Re-enable for debugging with enableTrace: true — not recommended in production.

❄️

Immutable Configuration

getConfigOptions() returns an isolated snapshot. Nested plain objects and arrays are cloned and frozen so middleware cannot mutate framework options.

🌊

Stream & Promise Safety

Stream errors are handled gracefully (connection terminates, no leak). Promise resolution is capped at depth 3 to prevent event loop starvation.

Quick Start

Common patterns to get you moving fast.

basic-server.js
const restana = require('restana')

const service = restana()
service.get('/hi', (req, res) => res.send('Hello World!'))

service.start(3000)
https-server.js
const https = require('https')
const restana = require('restana')

const service = restana({
  server: https.createServer({
    key: keys.serviceKey,
    cert: keys.certificate
  })
})
service.get('/hi', (req, res) => res.send('Hello World!'))
service.start(3000)
json-api.js
service.get('/api/users', (req, res) => {
  res.send({ users: [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
  ]})
})
async-handler.js
service.get('/users/:id', async (req, res) => {
  const user = await db.findById(req.params.id)
  if (!user) {
    res.statusCode = 404
    return res.send('Not found')
  }
  res.send(user)
})
nested-routers.js
const nestedRouter = service.newRouter()

nestedRouter.get('/hello', (req, res) => {
  res.send('Hello World!')
})
// Mount under /v1
service.use('/v1', nestedRouter)
middleware.js
// Global logger
service.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`)
  return next()
})

// Route-level auth
service.get('/admin', auth, (req, res) => {
  res.send('Welcome, admin')
})

Core Capabilities

Everything you need, nothing you don't.

1. HTTP Routing

restana supports all standard HTTP methods with a clean, chainable API.

  • GET, DELETE, PUT, PATCH, POST, HEAD, OPTIONS — plus service.all() for universal handlers
  • TRACE is disabled by default (re-enable with enableTrace: true)
  • Route matching uses an internal LRU cache — routerCacheSize controls cache depth (default: 2000)

2. The res.send() Method

One method handles every response type. No res.json(), res.text(), or res.stream() needed.

  • null / undefined — empty response
  • Boolean — application/json
  • String — text/plain
  • Buffer — application/octet-stream
  • Object — application/json
  • Stream — piped with graceful error handling
  • Promise — resolved recursively (depth cap: 3)

Full signature: res.send(data, statusCode, headers, callback). You can also send just a status code: res.send(401).

3. Middleware Support

All middlewares using the (req, res, next) signature are compatible — including Express middleware from npm.

Global Middleware

Applies to every route. Use for logging, CORS, authentication.

Prefix Middleware

Scoped to a path prefix. service.use('/admin', authMiddleware)

Route-Level Middleware

Multiple callbacks per route, including arrays of middleware functions.

Async Middleware (v3.3+)

Full async/await support. Catch uncaught exceptions in the request processing flow with try/catch wrappers.

4. Custom Servers & Events

Server-agnostic. Use standard http.Server, https.Server, or your own implementation.

  • service.start(port) — returns a Promise with the server instance
  • service.close() — graceful shutdown
  • service.callback() — standard (req, res) handler for third-party integrations
  • service.events.BEFORE_ROUTE_REGISTER — hook into route registration

Get Started

One command and you're running.

Configuration Options

Pass an options object to restana(config) — everything is optional.

OptionDescriptionDefault
serverCustom HTTP server instancehttp.createServer()
prioRequestsProcessingUse setImmediate for priority processingtrue
defaultRouteHandler for unmatched routes (404)res.send(404)
errorHandlerGlobal error handler functionSafe by default
routerCacheSizeRoute match cache size2000
enableTraceEnable TRACE HTTP methodfalse
securityHeadersSet default security headers on every responsetrue
trustProxyTrust forwarded protocol for HSTSfalse
debugErrorsExpose local error details (never in production)false
custom-error-handler.js
const service = restana({
  errorHandler(err, req, res) {
    console.error(`Error: ${err.message}`)
    res.send({ error: 'Internal Server Error' }, 500)
  }
})
https-custom-server.js
const https = require('https')
const fs = require('fs')
const service = restana({
  server: https.createServer({
    key: fs.readFileSync('key.pem'),
    cert: fs.readFileSync('cert.pem')
  })
})
service.start(443)
custom-404.js
const service = restana({
  defaultRoute(req, res) {
    res.statusCode = 404
    res.send({ path: req.url, error: 'Not Found' })
  }
})
disable-cache.js
const service = restana({
  routerCacheSize: 0  // disable LRU cache
})
// Or: unlimited cache (useful for many static routes)
// routerCacheSize: -1
enable-trace-debug.js
const service = restana({
  enableTrace: true
})
service.trace('/debug', (req, res) => {
  res.send('Echo: ' + req.url)
})
// ⚠️ Not recommended in production
disable-security-headers.js
const service = restana({
  securityHeaders: false
})
// Use when you manage headers yourself
// (e.g. with Helmet or for non-browser clients)
trusted-reverse-proxy.js
const service = restana({
  trustProxy: true
})
// Enable only when your proxy replaces
// client-supplied forwarded headers.
local-error-debugging.js
const service = restana({
  debugErrors: process.env.NODE_ENV === 'development'
})
// Production always masks error details.

Deploy Anywhere

restana works wherever Node.js runs — from serverless functions to dedicated servers.

☁️ AWS Lambda

Compatible with serverless-http. Wrap your service in a single handler and deploy as a Lambda function.

🔥 Cloud Functions for Firebase

Use service.callback() with functions.https.onRequest() for zero-config Firebase deployment.

📊 Elastic APM

Built-in routes naming plugin for Elastic APM. Instrument your service with restana/libs/elastic-apm.

📈 New Relic APM

Built-in routes naming plugin for New Relic. Attach before registering routes with restana/libs/newrelic-apm.

📄 Swagger / OpenAPI

Validate requests against OpenAPI specs with restana-swagger-validator. Available on npm.

📁 Static Files

Serve static assets with restana-static — a dedicated Docker container for frontend serving.