@maru

Fastify v6 Plugin Migration — Introducing createPlugin and Scope Types
As the official release of Fastify v6 approaches, preparing for plugin migration has become a critical task for the backend ecosystem. This major update goes beyond simple performance improvements, focusing on solving global type pollution—a persistent issue in TypeScript development environments.
The most notable changes are the introduction of a scope-based type system via fastify-plugin and the transition to the Undici v8 engine. I have summarized the key technical background to help you assess and address your internal plugins and dependencies for a stable migration.
Limitations of Declaration Merging and Type Pollution
In Fastify v5 and earlier, plugins used TypeScript declaration merging to define decorators. This involved injecting types directly into global interfaces using the declare module 'fastify' syntax. While easy to write, this approach had a structural flaw: once the compiler read even a small part of the code, types were forcibly merged across the entire application.
This caused issues where independent Fastify instances or isolated sub-routers that hadn't actually registered a specific plugin would have the type checker incorrectly assume the decorator existed. Consequently, in large monorepos or multi-instance environments, type safety was compromised because the compiler couldn't catch access to properties that didn't exist at runtime. Fastify v6 has transitioned to a new type structure to solve this persistent global type pollution problem.
fastify-plugin v6 and Solving Scope Types with createPlugin
To address global type pollution, the core Fastify team introduced a new factory helper, the fastify-plugin function, to the createPlugin package. Unlike the existing fp wrapper, which unconditionally merged types into the global scope and contaminated other isolated contexts, createPlugin provides registration scope mixin types that are valid only within the scope where the specific plugin is actually registered.
The following is a code guide comparing the existing global declaration merging method with the scope type-based mixin pattern of Fastify v6 and fastify-plugin v6.
// Before: Fastify v5 이하의 전역 선언 병합 방식
import fp from 'fastify-plugin';
declare module 'fastify' {
interface FastifyInstance {
customLog(message: string): void;
}
}
export default fp(async (fastify, opts) => {
fastify.decorate('customLog', (msg) => console.log(msg));
});// After: Fastify v6 및 fastify-plugin v6의 등록 스코프 타입 패턴
import { createPlugin } from 'fastify-plugin';
export interface MyLoggerMixin {
customLog(message: string): void;
}
// createPlugin 팩토리 헬퍼에 믹스인 인터페이스를 제네릭으로 전달합니다.
export default createPlugin<MyLoggerMixin>(async (fastify, opts) => {
fastify.decorate('customLog', (msg) => console.log(msg));
});By using the new method, the register decorator type is only activated within the area registered via the customLog function. This allows for complete type isolation in complex systems running multiple instances or monorepo architectures without polluting the global namespace.
Note that the Fastify v6 ecosystem mandates a minimum runtime version of Node.js v22.19.0 or higher to support the latest high-performance Undici v8 communication engine. In line with this high-performance runtime optimization, the global compiler pollution that has long been a developer experience bottleneck is being fundamentally improved through this type system redesign.
Undici v8 and Low-Level Migration of @fastify/reply-from
By integrating Undici v8—a high-performance HTTP client—as its internal engine, Fastify v6 requires compliance with the latest Node.js runtime and low-level API migration. To meet Undici v8 requirements, a runtime of Node.js v22.19.0 or higher is mandatory in Fastify v6 environments. Consequently, infrastructure runtime upgrades must be the first priority for operational environments currently using older Node.js versions.
The most critical technical change is the transition of the internal custom dispatcher architecture in Undici to the v2 API. This change directly impacts ecosystem plugins that act as proxies by intercepting or forwarding HTTP requests at a low level. A prime example is the traffic-forwarding plugin @fastify/reply-from, which must have its mechanisms fully revised to fit the new dispatcher interface specification.
In particular, the @fastify/reply-from library requires migration not only for the API shift but also to incorporate patches for the recently reported CVE-2026-16158 routing conflict vulnerability. For development teams managing their own API gateways or internal proxy layers, it is essential to move beyond just upgrading the Fastify version. You must also adjust your custom dispatcher code to meet the Undici v2 API specification and conduct rigorous verification regarding routing path conflicts.
Security and Version Matching — Mandatory Ecosystem Plugin Patches for 2026
When establishing a Fastify v6 migration roadmap, it is essential to simultaneously apply security patch versions across the entire ecosystem of plugins. High-risk security vulnerabilities disclosed throughout 2026 pose direct threats to service stability, necessitating management that goes beyond simple dependency updates.
One of the most urgent patch items is the response to the login CSRF vulnerability (CVE-2026-18165) in the @fastify/oauth2 plugin. Added since version v8.3.0, the hostPrefixedCookies option enforces the __Host- prefix for state and verifier cookies. This strictly regulates cookie write scopes to secure HTTPS origins and explicit hosts, effectively blocking session bypass attacks that exploit subdomains.
// @fastify/oauth2 v8.3.0+ 기준 설정
fastify.register(require('@fastify/oauth2'), {
name: 'googleOAuth2',
credentials: {
client: { id: 'CLIENT_ID', secret: 'CLIENT_SECRET' },
auth: require('@fastify/oauth2').GOOGLE_CONFIGURATION
},
startRedirectPath: '/login/google',
callbackUri: 'https://example.com/login/google/callback',
// CVE-2026-18165 취약점 방지를 위한 보안 강화 옵션
hostPrefixedCookies: true
});Key libraries handling authentication flows and resource processing must also meet minimum patch versions. @fastify/jwt, which had a key override bypass flaw at the request level, must be upgraded to v10.2.2 or higher (CVE-2026-18500). Furthermore, the multipart processing engine @fastify/multipart, which carried risks of file leakage and denial-of-service (DoS) attacks, requires v10.1.1 or higher (CVE-2026-19474, CVE-2026-18549).
Finally, @fastify/reply-from (which resolves the low-level proxy routing conflict vulnerability CVE-2026-16158) should also be included in your integrated update roadmap. Since Fastify v6 with Undici v8 requires a runtime of Node.js v22.19.0 or higher, you must first verify that your development machines, deployment containers, and plugin version compatibilities all align to avoid unexpected compatibility conflicts during migration.
Migration Roadmap for a Successful v6 Transition
Fastify v6 is being developed with an official release target of September 2026. After release, Fastify v5 will enter a phase of full support for 6 months, followed by an additional 6 months of security-only patches. While there is no immediate need for a full-scale migration, I recommend preparing incrementally to enjoy the benefits of the newly provided type isolation and V8-based performance optimizations. I suggest gradually transitioning your internal custom plugins' declaration merging dependencies to the createPlugin structure and proactively applying security patches for the major ecosystem plugins recently released to prepare for the next-generation transition.
Reference Links