Skip to content
English

Fastify backend

FastifyBackend is the default HTTP backend for actor-ts. Wraps Fastify — fast, well-maintained, with a huge ecosystem of plugins (JWT auth, validation, swagger, etc.).

import { ActorSystem, HttpExtensionId } from 'actor-ts';
const http = system.extension(HttpExtensionId);
await http.newServerAt('0.0.0.0', 8080).bind(routes);
// ↑ Fastify by default

To make the backend explicit:

import { FastifyBackend } from 'actor-ts/http';
await http.newServerAt('0.0.0.0', 8080)
.useBackend(new FastifyBackend())
.bind(routes);
new FastifyBackend({
logger: false, // Fastify's built-in logger — leave off; use actor-ts log
bodyLimit: 1_048_576, // 1 MiB request body cap
tls: {
cert: fs.readFileSync('./tls/cert.pem'),
key: fs.readFileSync('./tls/key.pem'),
},
});

Most settings pass through to Fastify’s FastifyServerOptions. The framework configures route registration; you tune Fastify’s own knobs.

Every response this backend writes carries X-Content-Type-Options: nosniff — its error mapping, the fallback 404 and the body-too-large 413 included, none of which a middleware sees. A response’s own header still wins.

Configure it per server, not per backend — one surface instead of three:

await http.newServerAt('0.0.0.0', 8080)
.useBackend(new FastifyBackend())
.withSecurityHeaders(false) // or a SecurityHeadersOptions bundle
.bind(routes);

See Security best practices.

new FastifyBackend({
tls: {
cert: fs.readFileSync('./tls/cert.pem'),
key: fs.readFileSync('./tls/key.pem'),
// For mTLS:
ca: fs.readFileSync('./tls/ca.pem'),
requestCert: true,
rejectUnauthorized: true,
},
});

Standard Fastify TLS options. For most production setups, TLS terminates at the load balancer — the app speaks plain HTTP internally — but in-app TLS is supported when needed.

const backend = new FastifyBackend();
await http.newServerAt('0.0.0.0', 8080)
.useBackend(backend)
.bind(routes);
// After bind, register a native plugin via the escape hatch...
await backend.withPlugin(fastifyJwt, { secret: '...' });
// ...or reach the raw Fastify instance for lower-level hooks:
backend.fastify.addHook('onRequest', authHook);

Use for plugins not exposed via the framework’s DSL:

  • JWT / OAuth authentication.
  • Request validation (@fastify/swagger).
  • CORS (@fastify/cors).
  • Compression.

The actor-ts DSL handles routing; Fastify plugins handle cross-cutting concerns. They compose cleanly.

1. new FastifyBackend() — the constructor creates the Fastify instance
2. The framework registers each compiled route on Fastify
3. Fastify.listen() — opens the port
4. On shutdown: Fastify.close() — drains in-flight requests, then exits

Fastify.close() waits for in-flight requests to complete before resolving — pairs with coordinated shutdown’s service-unbind phase.

Fastify is a hard dependency of actor-ts — it installs with the framework, so there’s nothing extra to add. (The Express and Hono backends, by contrast, are optional peer dependencies you install on demand.)

Rough numbers for trivial routes:

  • 150K-200K req/sec on Bun (with bun:test benchmark).
  • 80K-120K req/sec on Node 22.
  • P50 latency sub-millisecond for trivial handlers; higher for routes that ask actors.

Fastify is one of the fastest Node HTTP frameworks; the framework’s actor-routing overhead is the next bottleneck for hot routes.