Lesson 15 / 32
Encapsulation & Scope
Keep hooks, decorators and routes scoped inside plugins to build modular, conflict-free apps.
Plugin scope isolation
Plugins registered inside another plugin are scoped to that plugin. Decorators, hooks, and routes don't leak to sibling plugins.
Nested plugins
Create sub-apps by registering a plugin that registers child plugins.
// routes/v1.js
export default async function v1Routes(fastify, opts) {
fastify.get('/health', async () => ({ version: '1' }));
}
// routes/v2.js
export default async function v2Routes(fastify, opts) {
fastify.get('/health', async () => ({ version: '2' }));
}
// server.js
fastify.register(v1Routes, { prefix: '/v1' });
fastify.register(v2Routes, { prefix: '/v2' });
// GET /v1/health -> { version: '1' }
// GET /v2/health -> { version: '2' }Decorators stay inside their plugin
Each register creates a child context.
decoratein the child is invisible to the parent.- Wrap with
fastify-pluginif you want to share it upward.
const fastify = require('fastify')();
fastify.register(async (child) => {
child.decorate('secret', 42);
console.log('child', child.secret);
});
fastify.ready().then(() => {
console.log('parent', fastify.secret);
});
Output:
child 42 parent undefined
Quick check
Quick check: How do you make a plugin's decorator visible to the parent instance?
- Name the plugin `global`
- Wrap it with `fastify-plugin`
- Call `decorate` twice
Answer
Wrap it with `fastify-plugin` — `fastify-plugin` skips encapsulation so decorators and hooks apply to the parent.