Что такое middleware в Fastify и чем он отличается от Express?

JuniorFastify · Backend·Обновлено 10 сентября 2026
Коротко
В Fastify нет классического middleware как в Express — вместо этого используются хуки (hooks), привязанные к конкретным точкам жизненного цикла запроса, и инкапсулированные плагины. Совместимость с express-style middleware можно получить через плагин @fastify/middie, но нативный подход в Fastify другой и более производительный.

Middleware в Express

В Express middleware — это функция вида (req, res, next), которая выполняется последовательно для каждого запроса, проходящего через app.use(). Middleware может модифицировать req/res, завершать цикл ответа или передавать управление дальше вызовом next(). Ошибки передаются через next(err), и они попадают в специальный error-handling middleware с четырьмя аргументами (err, req, res, next).

Важная особенность Express — middleware выполняется линейно, одно за другим, без явной привязки к конкретной фазе обработки запроса (парсинг, валидация, авторизация и т.д. — всё это просто отдельные middleware в общей цепочке).

Как устроено в Fastify

Fastify спроектирован иначе: вместо единой цепочки middleware у него есть система хуков (hooks), каждый из которых привязан к конкретному этапу жизненного цикла запроса:

  • onRequest — самый ранний этап, до парсинга тела
  • preParsing — перед парсингом тела запроса
  • preValidation — перед валидацией по JSON-схеме
  • preHandler — перед основным обработчиком роута
  • preSerialization / onSend — перед отправкой ответа
  • onResponse, onError — после ответа / при ошибке

Хуки регистрируются через fastify.addHook('onRequest', async (request, reply) => {...}) и могут быть асинхронными — Fastify нативно построен вокруг async/await, поэтому вместо next(err) для сигнализации об ошибке достаточно просто выбросить исключение (throw) или вернуть отклонённый промис.

Инкапсуляция через плагины

Ещё одно ключевое отличие — инкапсуляция контекста. В Express всё, что зарегистрировано через app.use(), глобально влияет на всё приложение. В Fastify хуки и декораторы, зарегистрированные внутри плагина (fastify.register()), по умолчанию видны только внутри этого плагина и его дочерних роутов, а не во всём приложении. Это позволяет строить модульные, изолированные части API (например, разная авторизация для /public и /admin), не боясь случайно "утечь" логику в соседние модули.

Совместимость с express-style middleware

Поскольку многие разработчики привыкли к middleware-экосистеме Express (cors, helmet, morgan и т.д.), Fastify предоставляет официальный плагин @fastify/middie, который позволяет подключать обычные (req, res, next) middleware внутри Fastify-приложения:

await fastify.register(require('@fastify/middie'))
fastify.use(require('cors')())

Это в первую очередь механизм для миграции и переиспользования существующих Express-совместимых пакетов, а не основной способ работы с Fastify.

Почему это важно на собеседовании

  • Fastify быстрее Express во многом благодаря тому, что не тянет за собой универсальный слой middleware, а даёт точечные хуки только там, где они нужны
  • Встроенная валидация через JSON-схемы интегрирована в жизненный цикл (preValidation) — в Express это делается вручную через отдельные middleware
  • Асинхронная модель ошибок (throw/reject) вместо next(err) упрощает работу с async/await

Что хочет услышать интервьюер

Кандидат понимает базовую модель middleware в Express: (req, res, next), линейная цепочка, next(err) для ошибок

Кандидат знает, что в Fastify вместо middleware используются хуки, привязанные к конкретным фазам жизненного цикла запроса

Упоминание инкапсуляции — хуки/декораторы плагина не 'протекают' в глобальную область видимости

Понимание, что Fastify поддерживает express-style middleware через отдельный плагин (@fastify/middie), но это не основной подход

Связь архитектурных отличий с производительностью и встроенной JSON-schema валидацией

Пример: Middleware в Express

const express = require('express')
const app = express()

// обычное middleware — выполняется для каждого запроса
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`)
  next() // передаём управление дальше по цепочке
})

// middleware с проверкой авторизации
app.use('/admin', (req, res, next) => {
  if (!req.headers.authorization) {
    return next(new Error('Unauthorized')) // ошибка уходит в error-handler
  }
  next()
})

app.get('/admin/dashboard', (req, res) => {
  res.send('dashboard')
})

// error-handling middleware — четыре аргумента
app.use((err, req, res, next) => {
  res.status(401).send(err.message)
})

Пример: Эквивалент через хуки в Fastify

const fastify = require('fastify')()

// хук onRequest — выполняется на самом раннем этапе
fastify.addHook('onRequest', async (request, reply) => {
  console.log(`${request.method} ${request.url}`)
})

// плагин с инкапсулированной проверкой авторизации
// хук ниже действует только внутри этого плагина, а не глобально
fastify.register(async function adminPlugin(instance) {
  instance.addHook('preHandler', async (request, reply) => {
    if (!request.headers.authorization) {
      // просто бросаем ошибку — не нужен next(err)
      throw new Error('Unauthorized')
    }
  })

  instance.get('/admin/dashboard', async (request, reply) => {
    return 'dashboard'
  })
}, { prefix: '/admin' })

// глобальный обработчик ошибок
fastify.setErrorHandler((err, request, reply) => {
  reply.status(401).send({ error: err.message })
})

Типичные ошибки

Утверждение, что в Fastify middleware работает точно так же, как в Express, просто с другим синтаксисом

Незнание про инкапсуляцию плагинов — предположение, что всё зарегистрированное глобально видно везде, как в Express

Путаница между хуками (onRequest, preHandler и т.д.) и плагинами — кандидат считает их одним и тем же механизмом

Забывают, что для ошибок в Fastify достаточно throw/reject, и пытаются описывать next(err)-подобный паттерн

Не знают о существовании @fastify/middie и утверждают, что Express-middleware в Fastify использовать вообще нельзя

Лучшие курсы по теме

изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Node.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее