|  |  | # V3 Migration Guide
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | This guide is intended to help with migration from Fastify v2 to v3.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Before beginning please ensure that any deprecation warnings from v2 are fixed.
 | 
						
						
						
							|  |  | All v2 deprecations have been removed and they will no longer work after
 | 
						
						
						
							|  |  | upgrading. ([#1750](https://github.com/fastify/fastify/pull/1750))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Breaking changes
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed middleware support ([#2014](https://github.com/fastify/fastify/pull/2014))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | From Fastify v3, middleware support does not come out-of-the-box with the
 | 
						
						
						
							|  |  | framework itself.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If you use Express middleware in your application, please install and register
 | 
						
						
						
							|  |  | the [`@fastify/express`](https://github.com/fastify/fastify-express) or
 | 
						
						
						
							|  |  | [`middie`](https://github.com/fastify/middie) plugin before doing so.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | // Using the Express `cors` middleware in Fastify v2.
 | 
						
						
						
							|  |  | fastify.use(require('cors')());
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | // Using the Express `cors` middleware in Fastify v3.
 | 
						
						
						
							|  |  | await fastify.register(require('@fastify/express'));
 | 
						
						
						
							|  |  | fastify.use(require('cors')());
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed logging serialization ([#2017](https://github.com/fastify/fastify/pull/2017))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The logging [Serializers](../Reference/Logging.md) have been updated to now
 | 
						
						
						
							|  |  | Fastify [`Request`](../Reference/Request.md) and
 | 
						
						
						
							|  |  | [`Reply`](../Reference/Reply.md) objects instead of native ones.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | Any custom serializers must be updated if they rely upon `request` or `reply`
 | 
						
						
						
							|  |  | properties that are present on the native objects but not the Fastify objects.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const fastify = require('fastify')({
 | 
						
						
						
							|  |  |   logger: {
 | 
						
						
						
							|  |  |     serializers: {
 | 
						
						
						
							|  |  |       res(res) {
 | 
						
						
						
							|  |  |         return {
 | 
						
						
						
							|  |  |           statusCode: res.statusCode,
 | 
						
						
						
							|  |  |           customProp: res.customProp
 | 
						
						
						
							|  |  |         };
 | 
						
						
						
							|  |  |       }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | });
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const fastify = require('fastify')({
 | 
						
						
						
							|  |  |   logger: {
 | 
						
						
						
							|  |  |     serializers: {
 | 
						
						
						
							|  |  |       res(reply) {
 | 
						
						
						
							|  |  |         return {
 | 
						
						
						
							|  |  |           statusCode: reply.statusCode, // No change required
 | 
						
						
						
							|  |  |           customProp: reply.raw.customProp // Log custom property from res object
 | 
						
						
						
							|  |  |         };
 | 
						
						
						
							|  |  |       }
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | });
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed schema substitution ([#2023](https://github.com/fastify/fastify/pull/2023))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The non-standard `replace-way` shared schema support has been removed. This
 | 
						
						
						
							|  |  | feature has been replaced with JSON Schema specification compliant `$ref` based
 | 
						
						
						
							|  |  | substitution. To help understand this change read [Validation and Serialization
 | 
						
						
						
							|  |  | in Fastify
 | 
						
						
						
							|  |  | v3](https://dev.to/eomm/validation-and-serialization-in-fastify-v3-2e8l).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const schema = {
 | 
						
						
						
							|  |  |   body: 'schemaId#'
 | 
						
						
						
							|  |  | };
 | 
						
						
						
							|  |  | fastify.route({ method, url, schema, handler });
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const schema = {
 | 
						
						
						
							|  |  |   body: {
 | 
						
						
						
							|  |  |     $ref: 'schemaId#'
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | };
 | 
						
						
						
							|  |  | fastify.route({ method, url, schema, handler });
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed schema validation options ([#2023](https://github.com/fastify/fastify/pull/2023))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The `setSchemaCompiler` and `setSchemaResolver` options have been replaced with
 | 
						
						
						
							|  |  | the `setValidatorCompiler` to enable future tooling improvements. To help
 | 
						
						
						
							|  |  | understand this change read [Validation and Serialization in Fastify
 | 
						
						
						
							|  |  | v3](https://dev.to/eomm/validation-and-serialization-in-fastify-v3-2e8l).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const fastify = Fastify();
 | 
						
						
						
							|  |  | const ajv = new AJV();
 | 
						
						
						
							|  |  | ajv.addSchema(schemaA);
 | 
						
						
						
							|  |  | ajv.addSchema(schemaB);
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | fastify.setSchemaCompiler(schema => ajv.compile(schema));
 | 
						
						
						
							|  |  | fastify.setSchemaResolver(ref => ajv.getSchema(ref).schema);
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | const fastify = Fastify();
 | 
						
						
						
							|  |  | const ajv = new AJV();
 | 
						
						
						
							|  |  | ajv.addSchema(schemaA);
 | 
						
						
						
							|  |  | ajv.addSchema(schemaB);
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | fastify.setValidatorCompiler(({ schema, method, url, httpPart }) =>
 | 
						
						
						
							|  |  |   ajv.compile(schema)
 | 
						
						
						
							|  |  | );
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed preParsing hook behavior ([#2286](https://github.com/fastify/fastify/pull/2286))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | From Fastify v3, the behavior of the `preParsing` hook will change slightly in
 | 
						
						
						
							|  |  | order to support request payload manipulation.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The hook now takes an additional argument, `payload`, and therefore the new hook
 | 
						
						
						
							|  |  | signature is `fn(request, reply, payload, done)` or `async fn(request, reply,
 | 
						
						
						
							|  |  | payload)`.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The hook can optionally return a new stream via `done(null, stream)` or
 | 
						
						
						
							|  |  | returning the stream in case of async functions.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | If the hook returns a new stream, it will be used instead of the original one in
 | 
						
						
						
							|  |  | subsequent hooks. A sample use case for this is handling compressed requests.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The new stream should add the `receivedEncodedLength` property to the stream
 | 
						
						
						
							|  |  | that should reflect the actual data size received from the client. For instance,
 | 
						
						
						
							|  |  | in a compressed request it should be the size of the compressed payload. This
 | 
						
						
						
							|  |  | property can (and should) be dynamically updated during `data` events.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The old syntax of Fastify v2 without payload is supported but it is deprecated.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed hooks behavior ([#2004](https://github.com/fastify/fastify/pull/2004))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | From Fastify v3, the behavior of `onRoute` and `onRegister` hooks will change
 | 
						
						
						
							|  |  | slightly in order to support hook encapsulation.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | - `onRoute` - The hook will be called asynchronously. The hook is now inherited
 | 
						
						
						
							|  |  |   when registering a new plugin within the same encapsulation scope. Thus, this
 | 
						
						
						
							|  |  |   hook should be registered _before_ registering any plugins.
 | 
						
						
						
							|  |  | - `onRegister` - Same as the onRoute hook. The only difference is that now the
 | 
						
						
						
							|  |  |   very first call will no longer be the framework itself, but the first
 | 
						
						
						
							|  |  |   registered plugin.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed Content Type Parser syntax ([#2286](https://github.com/fastify/fastify/pull/2286))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | In Fastify v3 the content type parsers now have a single signature for parsers.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The new signatures are `fn(request, payload, done)` or `async fn(request,
 | 
						
						
						
							|  |  | payload)`. Note that `request` is now a Fastify request, not an
 | 
						
						
						
							|  |  | `IncomingMessage`. The payload is by default a stream. If the `parseAs` option
 | 
						
						
						
							|  |  | is used in `addContentTypeParser`, then `payload` reflects the option value
 | 
						
						
						
							|  |  | (string or buffer).
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The old signatures `fn(req, [done])` or `fn(req, payload, [done])` (where `req`
 | 
						
						
						
							|  |  | is `IncomingMessage`) are still supported but are deprecated.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Changed TypeScript support
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | The type system was changed in Fastify version 3. The new type system introduces
 | 
						
						
						
							|  |  | generic constraining and defaulting, plus a new way to define schema types such
 | 
						
						
						
							|  |  | as a request body, querystring, and more!
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```ts
 | 
						
						
						
							|  |  | interface PingQuerystring {
 | 
						
						
						
							|  |  |   foo?: number;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | interface PingParams {
 | 
						
						
						
							|  |  |   bar?: string;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | interface PingHeaders {
 | 
						
						
						
							|  |  |   a?: string;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | interface PingBody {
 | 
						
						
						
							|  |  |   baz?: string;
 | 
						
						
						
							|  |  | }
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | server.get<PingQuerystring, PingParams, PingHeaders, PingBody>(
 | 
						
						
						
							|  |  |   '/ping/:bar',
 | 
						
						
						
							|  |  |   opts,
 | 
						
						
						
							|  |  |   (request, reply) => {
 | 
						
						
						
							|  |  |     console.log(request.query); // This is of type `PingQuerystring`
 | 
						
						
						
							|  |  |     console.log(request.params); // This is of type `PingParams`
 | 
						
						
						
							|  |  |     console.log(request.headers); // This is of type `PingHeaders`
 | 
						
						
						
							|  |  |     console.log(request.body); // This is of type `PingBody`
 | 
						
						
						
							|  |  |   }
 | 
						
						
						
							|  |  | );
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```ts
 | 
						
						
						
							|  |  | server.get<{
 | 
						
						
						
							|  |  |   Querystring: PingQuerystring;
 | 
						
						
						
							|  |  |   Params: PingParams;
 | 
						
						
						
							|  |  |   Headers: PingHeaders;
 | 
						
						
						
							|  |  |   Body: PingBody;
 | 
						
						
						
							|  |  | }>('/ping/:bar', opts, async (request, reply) => {
 | 
						
						
						
							|  |  |   console.log(request.query); // This is of type `PingQuerystring`
 | 
						
						
						
							|  |  |   console.log(request.params); // This is of type `PingParams`
 | 
						
						
						
							|  |  |   console.log(request.headers); // This is of type `PingHeaders`
 | 
						
						
						
							|  |  |   console.log(request.body); // This is of type `PingBody`
 | 
						
						
						
							|  |  | });
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ### Manage uncaught exception ([#2073](https://github.com/fastify/fastify/pull/2073))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | In sync route handlers, if an error was thrown the server crashed by design
 | 
						
						
						
							|  |  | without calling the configured `.setErrorHandler()`. This has changed and now
 | 
						
						
						
							|  |  | all unexpected errors in sync and async routes are managed.
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v2:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | fastify.setErrorHandler((error, request, reply) => {
 | 
						
						
						
							|  |  |   // this is NOT called
 | 
						
						
						
							|  |  |   reply.send(error)
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | fastify.get('/', (request, reply) => {
 | 
						
						
						
							|  |  |   const maybeAnArray = request.body.something ? [] : 'I am a string'
 | 
						
						
						
							|  |  |   maybeAnArray.substr() // Thrown: [].substr is not a function and crash the server
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | **v3:**
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ```js
 | 
						
						
						
							|  |  | fastify.setErrorHandler((error, request, reply) => {
 | 
						
						
						
							|  |  |   // this IS called
 | 
						
						
						
							|  |  |   reply.send(error)
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | fastify.get('/', (request, reply) => {
 | 
						
						
						
							|  |  |   const maybeAnArray = request.body.something ? [] : 'I am a string'
 | 
						
						
						
							|  |  |   maybeAnArray.substr() // Thrown: [].substr is not a function, but it is handled
 | 
						
						
						
							|  |  | })
 | 
						
						
						
							|  |  | ```
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | ## Further additions and improvements
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | - Hooks now have consistent context regardless of how they are registered
 | 
						
						
						
							|  |  |   ([#2005](https://github.com/fastify/fastify/pull/2005))
 | 
						
						
						
							|  |  | - Deprecated `request.req` and `reply.res` for
 | 
						
						
						
							|  |  |   [`request.raw`](../Reference/Request.md) and
 | 
						
						
						
							|  |  |   [`reply.raw`](../Reference/Reply.md)
 | 
						
						
						
							|  |  |   ([#2008](https://github.com/fastify/fastify/pull/2008))
 | 
						
						
						
							|  |  | - Removed `modifyCoreObjects` option
 | 
						
						
						
							|  |  |   ([#2015](https://github.com/fastify/fastify/pull/2015))
 | 
						
						
						
							|  |  | - Added [`connectionTimeout`](../Reference/Server.md#factory-connection-timeout)
 | 
						
						
						
							|  |  |   option ([#2086](https://github.com/fastify/fastify/pull/2086))
 | 
						
						
						
							|  |  | - Added [`keepAliveTimeout`](../Reference/Server.md#factory-keep-alive-timeout)
 | 
						
						
						
							|  |  |   option ([#2086](https://github.com/fastify/fastify/pull/2086))
 | 
						
						
						
							|  |  | - Added async-await support for [plugins](../Reference/Plugins.md#async-await)
 | 
						
						
						
							|  |  |   ([#2093](https://github.com/fastify/fastify/pull/2093))
 | 
						
						
						
							|  |  | - Added the feature to throw object as error
 | 
						
						
						
							|  |  |   ([#2134](https://github.com/fastify/fastify/pull/2134))
 |