Fastify's built in validator uses Ajv with coerceTypes set to array, useDefaults true, removeAdditional true and allErrors false. That means validation can change your data: convert types, fill defaults and delete extra properties. Know these behaviors before you rely on a schema as a security control.
The baseline configuration
The Fastify validation reference lists these defaults:
| Ajv option | Fastify value | Effect on a request |
|---|---|---|
| coerceTypes | array | Values are converted to match the schema type, and single values can become arrays |
| useDefaults | true | Missing properties are filled from default keywords |
| removeAdditional | true | Extra properties are removed when additionalProperties is false |
| allErrors | false | Stops at first error. The docs warn true allows a denial of service attack |
You can change the baseline through the ajv.customOptions setting on the Fastify factory.
Coercion in practice
With coerceTypes, a query string value of "1" for a number field becomes the number 1. The docs show that with the array setting, a querystring like ?ids=1 against an array typed field arrives as an array containing "1". Coercion makes query handling easier, but it also means a field can be typed differently from what the client sent, and a schema that is too loose accepts oddly shaped input.
The docs also say to evaluate this behavior and verify it meets your project requirements. They show how to give body, params, querystring and headers different Ajv instances, for example disabling coercion for body only.
Why removeAdditional matters for security
It strips unexpected properties instead of failing, but only where the schema sets additionalProperties to false. Without that, extra fields pass through untouched. Teams often assume a schema blocks extra fields. It does not unless you say so.
| Goal | Schema setting |
|---|---|
| Reject unknown fields | additionalProperties false and removeAdditional false |
| Silently drop unknown fields | additionalProperties false with the default removeAdditional |
| Allow anything | Leave additionalProperties unset |
Steps
- Write a schema for every route's body, query, params and headers.
- Set additionalProperties to false on request objects.
- Decide strip or reject, and configure removeAdditional to match.
- Set maximum lengths on strings and arrays, and bounds on numbers.
- Leave allErrors at false unless you have a reason, per the docs warning.
- Add tests that send wrong types, extra fields and oversized values.
const schema = {
body: {
type: 'object',
required: ['name'],
additionalProperties: false,
properties: {
name: { type: 'string', maxLength: 100 }
}
}
};
fastify.post('/users', { schema }, handler);
Where validation stops
A schema checks shape, not authorization or business rules. It also runs after the body has been read, so size limits still matter. See Fastify bodyLimit. For the NestJS equivalent, see ValidationPipe options.
Try it yourself
Click through it at your own pace, or open it full screen.
Click through the results and look at findings about missing input constraints.
Safeguard's API security scan and dependency scanning can review exposed endpoints and the validation packages behind them. Free scan: gold.safeguard.sh/scan.
Quick check
Does Fastify reject unknown body fields by default?
No. It removes them only when the schema sets additionalProperties to false. Otherwise they pass through.
Can validation change the value my handler sees?
Yes. Coercion and defaults modify the data, so your handler may see different types than the client sent.
Sources
Last reviewed: 19 October 2026.