Fastify: Das schnellste Node.js-Framework für hochperformante APIs

Wenn es um rohe Performance bei Node.js-APIs geht, führt kaum ein Weg an Fastify vorbei. Das Framework wurde von Grund auf mit Geschwindigkeit als primärem Ziel entwickelt und setzt dabei auf einen cleveren Einsatz von JSON-Schema-Validierung, hochoptimierter Serialisierung und einem modularen Plugin-System. Dieser Artikel erklärt, warum Fastify in immer mehr Projekten Express ablöst und welche Konzepte das Framework auszeichnen.

Was ist Fastify?

Fastify ist ein Web-Framework für Node.js, das 2016 von Matteo Collina und Tomas Della Vedova initiiert wurde. Es ist heute eines der am aktivsten weiterentwickelten Node.js-Frameworks und wird von einer großen Community gepflegt. Im Gegensatz zu Express setzt Fastify auf strikte Schema-Validierung und nutzt diese nicht nur zur Fehlerprüfung, sondern auch zur drastischen Beschleunigung der JSON-Serialisierung.

Die vollständige Dokumentation ist unter fastify.dev verfügbar und gilt als vorbildlich strukturiert.

JSON Schema Validierung

Fastify verwendet AJV (Another JSON Validator) zur Validierung von Request-Daten. Jede Route kann Schemas für den Request-Body, Query-Parameter, URL-Parameter und den Response definieren. Das bringt zwei wesentliche Vorteile:

Erstens werden ungültige Anfragen automatisch mit einem strukturierten Fehler abgelehnt, bevor sie den Handler erreichen. Zweitens nutzt Fastify das Response-Schema zur Vorabkompilierung eines schnellen JSON-Serialisierers (fast-json-stringify), der die Antwort deutlich schneller serialisiert als JSON.stringify().

const userSchema = {
  type: 'object',
  properties: {
    id:    { type: 'integer' },
    name:  { type: 'string' },
    email: { type: 'string', format: 'email' }
  },
  required: ['name', 'email']
};

Typisches Routen-Beispiel mit Schema

So sieht eine vollständige Fastify-Route mit Schema-Validierung aus:

fastify.post('/users', {
  schema: {
    body: {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        name:  { type: 'string', minLength: 2 },
        email: { type: 'string', format: 'email' }
      }
    },
    response: {
      201: {
        type: 'object',
        properties: {
          id:    { type: 'integer' },
          name:  { type: 'string' },
          email: { type: 'string' }
        }
      }
    }
  }
}, async (request, reply) => {
  const user = await userService.create(request.body);
  return reply.status(201).send(user);
});

Das Schema beschreibt sowohl Eingabe als auch Ausgabe exakt. Fastify serialisiert den Response ausschließlich mit den im Schema definierten Feldern – das verhindert versehentliche Datenlecks und beschleunigt die Ausgabe gleichzeitig.

Plugin-Architektur

Fastifys Plugin-System ist das architektonische Herzstück des Frameworks. Jede Erweiterung – ob Datenbankverbindung, Authentifizierung, CORS oder Caching – wird als Plugin registriert. Plugins haben ihren eigenen Scope: Was innerhalb eines Plugins registriert wird, ist außerhalb nicht automatisch sichtbar, sofern es nicht explizit mit fastify-plugin dekoriert wird.

Dieses Scoping-Prinzip ermöglicht echte Modularität: Verschiedene API-Versionen können in getrennten Plugins laufen, jede mit eigenen Middlewares und Hooks, ohne sich gegenseitig zu beeinflussen. Das offizielle Ökosystem unter fastify.dev/ecosystem enthält Plugins für PostgreSQL, MongoDB, Redis, JWT, Swagger und vieles mehr.

Hooks-Lifecycle

Fastify bietet einen detaillierten Anfrage-Lifecycle mit mehreren Hook-Punkten, an denen eigene Logik eingehängt werden kann:

Hooks können global, auf Plugin-Ebene oder für einzelne Routen definiert werden.

Tipp: Nutze den preHandler-Hook für Authentifizierung und Autorisierung. Kombiniert mit fastify-jwt lässt sich damit eine saubere, deklarative Zugriffskontrolle auf Route-Ebene implementieren – einfach mit preHandler: [fastify.authenticate] in der Routen-Definition.

TypeScript-Support

Fastify bietet erstklassigen TypeScript-Support direkt aus der Box. Die Typdefinitionen sind Teil des Hauptpakets und spiegeln die gesamte API inklusive Generics für Request- und Response-Typen wider. Routen lassen sich vollständig typisieren:

interface CreateUserBody {
  name: string;
  email: string;
}

fastify.post<{ Body: CreateUserBody }>('/users', async (request, reply) => {
  // request.body ist vollständig typisiert
  const { name, email } = request.body;
  return reply.status(201).send({ id: 1, name, email });
});

Logging mit Pino

Fastify integriert Pino als Standard-Logger. Pino ist einer der schnellsten Node.js-Logger und nutzt JSON-Ausgabe, was die maschinelle Verarbeitbarkeit in Log-Management-Systemen wie Elasticsearch oder Datadog vereinfacht. Das Logging ist in Fastify von Haus aus aktiviert und auf jeder Anfrage und Antwort automatisch vorhanden:

const fastify = require('fastify')({ logger: true });
// Jede Route loggt automatisch Zeitstempel, URL, Status und Latenz

In der Entwicklung empfiehlt sich pino-pretty für eine lesbare, formatierte Konsolenausgabe.

Achtung: Die Plugin-Reihenfolge und das Scoping-System in Fastify können anfangs verwirrend sein. Wer ein Plugin außerhalb seines Scopes verwenden möchte (z. B. eine Datenbankverbindung, die überall verfügbar sein soll), muss das Plugin mit fastify-plugin wrappen. Fehlt dieses Wrapping, ist der Dekorator in anderen Plugins nicht verfügbar, was zu schwer zu debuggenden Laufzeitfehlern führt.

Benchmarks: Fastify vs. Express

In standardisierten Benchmarks (Autocannon, wrk) erzielt Fastify je nach Testkonfiguration zwischen 50 % und 100 % mehr Requests pro Sekunde als Express. Der Hauptgrund liegt in der optimierten JSON-Serialisierung durch vorab kompilierte Serialisierer sowie in einer effizienteren Routing-Implementierung mit find-my-way.

Vergleich: Fastify vs. Express vs. Hono vs. NestJS

Kriterium Fastify Express Hono NestJS
Performance Sehr hoch Mittel Sehr hoch (Edge) Mittel (Express-Basis)
Schema-Validierung Eingebaut (JSON Schema) Externe Pakete Via Zod/Valibot Via class-validator
TypeScript First-class, eingebaut Via @types/express First-class, eingebaut First-class (TypeScript-first)
Plugin-Ökosystem Groß, offiziell gepflegt Sehr groß Wachsend Sehr groß (Module)
Lernkurve Mittel Niedrig Niedrig Hoch
Edge-Runtime Nein Nein Ja Nein

NestJS baut standardmäßig auf Express auf, kann aber auch als Adapter auf Fastify umgestellt werden, um dessen Performance-Vorteile zu nutzen. Die aktuelle Benchmark-Übersicht veröffentlicht das Fastify-Team regelmäßig auf der Benchmark-Seite des Projekts.

Häufig gestellte Fragen

Kann ich meine bestehende Express-Anwendung zu Fastify migrieren?
Eine vollständige Migration erfordert Anpassungsarbeit, da Fastify ein anderes Middleware-Modell und Plugin-System verwendet. Für eine schrittweise Migration empfiehlt sich das Paket @fastify/express, das Express-Middleware in Fastify nutzbar macht. Langfristig sollten Middlewares jedoch auf native Fastify-Hooks und -Plugins umgestellt werden.
Unterstützt Fastify WebSockets?
Ja, über das offizielle Plugin @fastify/websocket, das auf der ws-Bibliothek aufbaut. WebSocket-Handler können dabei direkt in Fastify-Routen definiert werden und profitieren vom selben Lifecycle wie HTTP-Routen.
Wie unterscheidet sich Fastifys Plugin-System von Express-Middleware?
Express-Middleware ist eine einfache Kette von Funktionen ohne Scope. Fastify-Plugins sind gekapselte Einheiten mit eigenem Gültigkeitsbereich. Was in einem Plugin registriert wird (Dekoratoren, Hooks, Routen), ist nur im jeweiligen Scope sichtbar. Das erzwingt eine bewusste Architektur und verhindert unbeabsichtigte globale Zustandsänderungen.
Ist Fastify für kleinere Projekte zu komplex?
Nein. Für einfache APIs braucht man nur wenige Zeilen, und das Plugin-System kommt erst bei größeren Projekten vollständig zum Tragen. Die klare Struktur und der eingebaute TypeScript-Support machen Fastify auch für kleine Projekte zu einer guten Wahl, wenn von Anfang an Wert auf Typsicherheit und Performance gelegt wird.