Fastify — веб-фреймворк для Node.js, который делает ставку на скорость, строгие схемы и предсказуемую структуру приложения. Вместо «магии» он даёт явные плагины, JSON Schema для проверки и сериализации, встроенный логгер на базе pino и удобные хуки. В 2026 году актуальная ветка требует современного Node.js и хорошо работает с TypeScript. Ниже — путь от пустого каталога до API с валидацией, тестами и нагрузочной проверкой.

Установка и первый сервер

Создайте проект и включите ES-модули. Версия Node.js должна быть не ниже требований фреймворка; проверьте её до установки зависимостей.

mkdir fastify-api
cd fastify-api
npm init -y
npm pkg set type=module
npm install fastify
node --version

Минимальный сервер занимает несколько строк. Встроенный логгер сразу пишет структурированный JSON, а listen возвращает ошибку, если порт занят или не хватает прав.

import Fastify from "fastify";

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

app.get("/health", async () => ({ status: "ok" }));

try {
  await app.listen({ port: 3000, host: "0.0.0.0" });
} catch (error) {
  app.log.error(error);
  process.exit(1);
}

Запустите node server.js и проверьте ответ через curl. Для разработки удобен node --watch server.js: процесс перезапускается при изменении файлов без сторонних пакетов.

Схемы: проверка и сериализация

Схема тела запроса отсекает лишние поля и возвращает понятную ошибку 400, если не хватает обязательных данных или тип не совпадает. Схема ответа не только документирует формат, но и ускоряет сериализацию: наружу попадут только объявленные свойства. Это заодно защищает от случайной утечки пароля или внутреннего идентификатора.

const userBody = {
  type: "object",
  required: ["email", "name"],
  additionalProperties: false,
  properties: {
    email: { type: "string", pattern: "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" },
    name: { type: "string", minLength: 1, maxLength: 80 }
  }
};

app.post("/users", {
  schema: {
    body: userBody,
    response: {
      201: {
        type: "object",
        properties: { id: { type: "integer" }, email: { type: "string" } }
      }
    }
  }
}, async (request, reply) => {
  const { email } = request.body;
  return reply.code(201).send({ id: 1, email });
});

Схемы стоит держать рядом с маршрутом или в отдельном модуле. Для повторного использования подойдёт addSchema и ссылки $ref. Помните, что format поддерживается не всеми конфигурациями Ajv, поэтому в примере используется регулярное выражение.

Плагины и структура проекта

Плагин — функция, которая получает экземпляр приложения. Fastify изолирует область видимости: декораторы и хуки, добавленные внутри плагина, не протекают наружу. Это позволяет собирать приложение из независимых модулей и не бояться конфликтов имён.

// routes/users.js
export default async function userRoutes(app) {
  app.get("/users/:id", async (request) => {
    return { id: Number(request.params.id) };
  });
}

// server.js
import userRoutes from "./routes/users.js";
app.register(userRoutes, { prefix: "/api" });
await app.ready();

Если плагин должен изменить родительский экземпляр, его оборачивают в fastify-plugin. Типичный пример — подключение пула базы данных и декоратор app.db. Для автоматической загрузки каталогов есть @fastify/autoload, но в маленьком проекте проще явный список.

Хуки и обработка ошибок

Хуки выполняются на разных стадиях: onRequest подходит для проверки токена, preHandler — для загрузки сущности, onSend — для правки ответа. Единый обработчик ошибок не должен отдавать стек клиенту в production.

app.addHook("onRequest", async (request) => {
  request.startAt = Date.now();
});

app.setErrorHandler((error, request, reply) => {
  request.log.error(error);
  const status = error.statusCode ?? 500;
  reply.code(status).send({
    error: status === 500 ? "internal error" : error.message
  });
});

Для валидации, CORS, безопасности и ограничения частоты используйте официальные плагины @fastify/helmet, @fastify/cors и @fastify/rate-limit. Не добавляйте их «на всякий случай»: каждый плагин влияет на поведение и требует настройки под задачу.

Тесты без сетевых портов

Метод inject отправляет запрос прямо в приложение, без реального сокета. Это быстрее интеграционных тестов через HTTP и не конфликтует с занятыми портами.

import test from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "./app.js";

test("health", async () => {
  const app = buildApp();
  const response = await app.inject({ method: "GET", url: "/health" });
  assert.equal(response.statusCode, 200);
  assert.deepEqual(response.json(), { status: "ok" });
  await app.close();
});

Вынесите сборку приложения в app.js, а запуск сервера — в server.js. Тогда тесты не будут открывать порт, а конфигурация окружения останется в одном месте.

Производительность на практике

Скорость Fastify заметна на простых JSON-маршрутах, но её легко потерять из-за синхронных операций, тяжёлых ORM-запросов и отсутствия схем. Проверяйте гипотезы нагрузкой, а не только синтетическими цифрами из документации.

npm install -D autocannon
node server.js
npx autocannon -c 100 -d 10 http://127.0.0.1:3000/health
npx autocannon -c 100 -d 10 -m POST -b '{"email":"a@b.c","name":"A"}' http://127.0.0.1:3000/users

Смотрите не только на requests per second, но и на задержки p95 и p99, потребление памяти и ошибки. Для production включите NODE_ENV=production, настройте уровень логов и вынесите секреты в переменные окружения. За обратным прокси задайте trustProxy только для доверенных адресов, иначе клиент сможет подделать IP.

Безопасность и завершение работы

Ограничьте размер тела запроса, включите заголовки безопасности, добавьте лимит запросов на чувствительные маршруты. Корректное завершение по сигналу позволяет дождаться текущих запросов и закрыть соединения с базой.

const app = Fastify({
  logger: { level: "info", redact: ["req.headers.authorization"] },
  bodyLimit: 1048576,
  trustProxy: false
});

process.on("SIGTERM", async () => {
  await app.close();
  process.exit(0);
});
  • Валидируйте вход и ограничивайте ответ схемой.
  • Не логируйте токены и пароли, используйте redact.
  • Храните секреты вне репозитория.
  • Проверяйте зависимости через npm audit и обновляйте плагины.
  • Тестируйте не только успешные ответы, но и ошибки 400 и 500.

Итог

Fastify даёт строгую и быструю основу для API на Node.js: схемы, плагины, хуки и встроенный логгер складываются в понятную архитектуру. Начните с одного сервера и схемы здоровья, затем выделите маршруты в плагины, добавьте тесты через inject и проверьте нагрузку autocannon. Главное — не гнаться за бенчмарками в ущерб валидации и наблюдаемости.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте