intermediate

Fastify plugins

Explain plugin encapsulation, decorators, hooks, registration order, dependency declaration, and reusable service boundaries.

Fastify plugins encapsulate routes, decorators, and hooks inside a scope. `fastify-plugin` wraps plugins so decorators and hooks propagate correctly and metadata is preserved across encapsulation boundaries when intended.

					async function usersPlugin(fastify) {
  fastify.decorate('usersService', new UsersService());
  fastify.get('/users/:id', async (req) => {
    return fastify.usersService.find(req.params.id);
  });
}

app.register(usersPlugin, { prefix: '/api' });
				

Registration order matters: dependencies declare `dependencies: ['other-plugin']`. Encapsulation means child plugins do not see parent decorators unless `fastify-plugin` breaks the encapsulation chain deliberately.

On interviews: plugin encapsulation versus Express middleware globals, `decorate` for shared services, and hook lifecycle (`onRequest`, `preHandler`, `onResponse`).

Common pitfalls: registering plugins without `fastify-plugin` when decorators must be shared, circular plugin dependencies, and mixing sync registration with async boot incorrectly.

The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.

Checklist:

  • One plugin per feature boundary.
  • Use fastify-plugin when sharing decorators.
  • Declare plugin dependencies explicitly.
  • Mount with prefix for URL namespacing.