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.