DEV Community

Alex Spinov
Alex Spinov

Posted on

Fastify 5 Has a Free Web Framework: The Fastest Node.js Server With Built-In Validation, Logging, and Plugin System

Express handles 30,000 requests per second. Fastify handles 65,000+. Both use Node.js. The difference? Fastify was designed for performance from day one — JSON serialization, schema-based validation, and a plugin architecture that doesn't sacrifice speed.

If you're building APIs on Node.js and performance matters, Express is leaving money on the table.

Fastify 5 — What You Get

  • 2x Express throughput — 65,000+ req/s on a single core
  • JSON Schema validation — request/response validated automatically
  • Structured logging — Pino logger built in (30x faster than Winston)
  • Plugin system — encapsulated, composable, no global middleware soup
  • TypeScript-first — full type inference for routes, plugins, decorators
  • Auto-generated Swagger — from your JSON schemas

Quick Start

npm init fastify@latest my-api
cd my-api && npm install && npm run dev
Enter fullscreen mode Exit fullscreen mode

Basic Route With Validation

import Fastify from "fastify";

const app = Fastify({ logger: true });

app.post("/users", {
  schema: {
    body: {
      type: "object",
      required: ["name", "email"],
      properties: {
        name: { type: "string", minLength: 1 },
        email: { type: "string", format: "email" },
        age: { type: "integer", minimum: 0 },
      },
    },
    response: {
      201: {
        type: "object",
        properties: {
          id: { type: "string" },
          name: { type: "string" },
          email: { type: "string" },
        },
      },
    },
  },
  handler: async (request, reply) => {
    const { name, email, age } = request.body;
    const user = await db.users.create({ name, email, age });
    reply.code(201).send(user);
  },
});

app.listen({ port: 3000 });
Enter fullscreen mode Exit fullscreen mode

The response schema doesn't just validate — it strips extra fields and speeds up JSON serialization by knowing the shape ahead of time.

Plugin System — Encapsulated, Not Global

// plugins/database.ts
import fp from "fastify-plugin";

export default fp(async (fastify) => {
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });

  fastify.decorate("db", pool);

  fastify.addHook("onClose", async () => {
    await pool.end();
  });
});

// routes/users.ts
export default async function userRoutes(fastify) {
  fastify.get("/users", async (request) => {
    const { rows } = await fastify.db.query("SELECT * FROM users LIMIT 50");
    return rows;
  });

  fastify.get("/users/:id", async (request) => {
    const { rows } = await fastify.db.query("SELECT * FROM users WHERE id = $1", [request.params.id]);
    if (!rows[0]) throw fastify.httpErrors.notFound("User not found");
    return rows[0];
  });
}

// app.ts
app.register(import("./plugins/database"));
app.register(import("./routes/users"), { prefix: "/api" });
Enter fullscreen mode Exit fullscreen mode

Auto-Generated Swagger

import swagger from "@fastify/swagger";
import swaggerUi from "@fastify/swagger-ui";

app.register(swagger, {
  openapi: {
    info: { title: "My API", version: "1.0.0" },
  },
});
app.register(swaggerUi, { routePrefix: "/docs" });

// Your JSON schemas automatically become OpenAPI documentation
// Visit /docs for interactive API explorer
Enter fullscreen mode Exit fullscreen mode

Hooks — Lifecycle Control

app.addHook("onRequest", async (request, reply) => {
  // Runs before routing — auth, rate limiting
  const token = request.headers.authorization;
  if (!token) throw app.httpErrors.unauthorized();
  request.user = await verifyToken(token);
});

app.addHook("onSend", async (request, reply, payload) => {
  // Runs before sending response — add headers, transform
  reply.header("X-Request-Id", request.id);
  return payload;
});

app.addHook("onError", async (request, reply, error) => {
  // Centralized error handling
  request.log.error(error);
});
Enter fullscreen mode Exit fullscreen mode

Fastify 5 vs Express vs Hono

Feature Fastify 5 Express 4 Hono
Req/s (Node.js) 65,000+ 30,000 45,000*
Validation JSON Schema built-in Manual Zod/custom
Logging Pino (built-in) Morgan (add-on) Built-in
TypeScript First-class @types needed Native
Swagger gen From schemas Manual Manual
Plugin isolation Yes No (global middleware) Partial

*Hono on Node; on Bun it's faster.

When to Choose Fastify

Choose Fastify when:

  • Building production APIs on Node.js where performance matters
  • You want auto-generated docs from validation schemas
  • Structured logging is a requirement
  • You prefer plugins over global middleware chains

Skip Fastify when:

  • Simple prototype/MVP (Express is faster to start)
  • You're deploying to edge/serverless (Hono or Bun-native is better)
  • Your team knows Express and switching cost isn't justified

The Bottom Line

Fastify proves that Node.js APIs don't have to be slow. Built-in validation, logging, and plugin isolation give you production-grade features without the middleware spaghetti.

Start here: fastify.dev


Need custom data extraction, scraping, or automation? I build tools that collect and process data at scale — 78 actors on Apify Store and 265+ open-source repos. Email me: Spinov001@gmail.com | My Apify Actors

Top comments (0)