NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #3179 most downloaded on npm
Fast and low overhead web framework, for Node.js
Last release 18 days ago
16 Sep 2026
Release timing varies
gaps range from 8 days to 2 months
Nearly every release is documented
notes for 59 of the last 60 stable releases
67 versions withdrawn
withdrawn after publishing
10 years old
331 releases · first in 2016
Removed warnings introduced in #2418
📚 PR:
docs(readme): add my name and fix order
📚 PR:
Bump avvio to 7.1.1 and add a regression test
One column per quarter.
📚 PR:
Fix a wrong TypeScript typing issue at register() function
📚 PR:
feat(Serverless): Add netlify-lambda guide
📚 PR:
res.raw.statusCode typo (#2386)The old syntax of Fastify v2 without payload is supported but it is deprecated.
⚠️ When updating your application to Fastify v3, update all the module at once. There might be incompatibilities by trying to do them "one at a time".
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 plugin or middie plugin before doing so.
v2:
// Using the Express `cors` middleware in Fastify v2.
fastify.use(require('cors')());
v3:
// Using the Express `cors` middleware in Fastify v3.
await fastify.register(require('fastify-express'));
fastify.use(require('cors')());
The logging Serializers have been updated to Fastify Request and Reply 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:
const fastify = require('fastify')({
logger: {
serializers: {
res(res) {
return {
statusCode: res.statusCode,
customProp: res.customProp
};
}
}
}
});
v3:
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
};
}
}
}
});
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 better understand this change read Validation and Serialization in Fastify v3.
v2:
const schema = {
body: 'schemaId#'
};
fastify.route({ method, url, schema, handler });
v3:
const schema = {
body: {
$ref: 'schemaId#'
}
};
fastify.route({ method, url, schema, handler });
The setSchemaCompiler and setSchemaResolver options have been replaced with the setValidatorCompiler to enable future tooling improvements. To better understand this change read Validation and Serialization in Fastify v3.
v2:
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:
const fastify = Fastify();
const ajv = new AJV();
ajv.addSchema(schemaA);
ajv.addSchema(schemaB);
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) =>
ajv.compile(schema)
);
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 following 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.
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.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.
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:
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:
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`
});
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:
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:
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
})
request.req and reply.res for request.raw and reply.raw (#2008)modifyCoreObjects option (#2015)connectionTimeout option (#2086)keepAliveTimeout option (#2086)Disable allErrors in default Ajv config
📚 PR:
done in example (#2353)doc: replace compile-schemas-to-typescript with json-schema-to-typescript
test: Add test to verify async onClose hooks.
📚 PR:
fix docs: missing breaking change
First release candidate of v3. The migration guide can be found here.
First release candidate of v3. The migration guide can be found here.
release notes to come with full v3.0.0
release notes to come with full v3.0.0
inject function return normal value with non-ready app - #2417
Fixes:
📚 PR: - fix test per security release (#2365) - fix ready returns
📚 PR:
For security reasons we changed the default in the ajvconfiguration. Unfortunately allErrors: true is a DoS attack vector for certain schemas. So this
For security reasons we changed the default in the ajvconfiguration.
Unfortunately allErrors: true is a DoS attack vector for certain
schemas. So this changed to allErrors: false.
See: ajv-validator/ajv@334071a Ref: https://hackerone.com/reports/903521
PATCH to body validation (#2351)Bind error handler to instance (v2)
📚 PR:
Tweak haproxy config for issue #2036
Support builder-style injection
📚 PR:
ignore fast-json-stringify in dependabot
📚 PR:
Use light-my-request types instead of duplicating typings. fixes #2098
📚 PR:
add comma to queryStringJsonSchema
📚 PR:
setErrorHandler (#2092)this to the not found handler (#2102)fix: skip serialization for json string
📚 PR:
Test: After can access to decorations registered into plugin
📚 PR:
fix schema resolver for plain id - #1882
Features:
Fixes:
Documentation:
Improving Getting Started documentation
📚 PR:
docs(Serverless): add missing punctuation marks
📚 PR:
handler to RouteShorthandOptions (#1788)Ensure we are not running the handler if reply.sent is true - #1778
Fixes:
Documentation:
Added return503OnClosing option - #1723
Features:
return503OnClosing option - #1723Fixes:
Documentation:
next to done inside documentation - #1756feature: custom serializator - #1706
Features:
Documentation:
Add ability to get response time on reply - #1697
Features:
Fixes:
Documentation:
Add .git folder to NPM ignore - #1663
Use secure-json-parse instead of bourne
Features
Fixes
Documentation
fastify-decorators to Ecosystem.md (#1645)Internals
Add onRequest route hook - #1594
Features:
Fixes:
Documentation:
Internals:
Add option to match only prefix root with paths - #1487
Features:
Fixes:
Documentation:
genReqId being called even when 'request-id' header is supplied - #1566Test:
Internals:
feat: support more signatures for listen - #1463
Features:
Fixes:
Docs:
Internals:
fix: unused shared schema to serializer - #1496
Fixes:
Docs:
Internals:
Dependencies:
Update default ajv instance to include all errors (breaking change) - #1398
Official announcement: https://medium.com/@fastifyjs/8275d613fba4
Breaking changes:
Features:
Enhancements:
Fixes:
TypeScript:
Documentation:
Allow override of the default content-type parser inside a plugin - #1435
Fixes
Update default ajv instance to include all errors *(breaking change)* - #1398
Features
Enhancements
Fixes
TypeScript
Documentation
Internals
Test
Add plugin name in case of dependency error - #1371
Features
Enhancements
Fixes
TypeScript
Documentation
Internals
Test
Establish reply.sent = true as a proper way to skip async/await handling - #1336
Fixes
Documentation
PR to fix issue #1269 - add plain text parser to core - #1280
Features
Dependencies
Typescript
Internals
Documentation
chore: pin ajv to 6.5.5 - #1282
https://medium.com/@fastifyjs/fastify-v2-is-coming-to-town-ce279738bed6
Welcome Fastify v2 🚀
https://medium.com/@fastifyjs/fastify-v2-is-coming-to-town-ce279738bed6
Breaking changes
req.id in serializer - #1032Type this in RequestHandler - #1539
Fixes:
Test: - Fix #1537 - #1545
Test:
feat: add pluginTimeout options in d.ts - #1527
Fixes:
fix: unused shared schema to serializer - #1502
Fixes:
fix: don't add twice a json schema to an encapsulated object in tree - #1462
Fixes:
Allow override of the default content-type parser inside a plugin - #1434
Fixes
Support custom route versioning strategies - #1422
Features
Fixes
move ECONNRESET log from error to debug - #1363
Enhancements
Fixes
Documentation
Handle response validation error - #1328
Fixes
update ajv and autocannon to the latest versions https://github.com/fastify/fastify/pull/1296
chore: pin ajv to 6.5.5 - #1282
Enable nested plugins to override decorators - #1199
Features
Enhancements
Fixes
fastify-babel - #1219Typescript
Documentation
fastify-babel - #1219Fix content length for utf-8 characters #1187
Add badge of vulnerabilities from snyk.io - #1149
Enhancements
Fixes
Typescript
Internals
Documentation
Handle promises in the error handler with the same logic of normal handlers - #1134
Internals
Documentation
Add fastify-file-upload to ecosystem https://github.com/fastify/fastify/pull/1106
Your coding agent can read these notes before it upgrades. Set up the MCP server →