Fastify bodyLimit: does a route-level override fully replace the global limit for all content types?
0 reputation · 02 Sept 2024, 22:01 UTC
0 reputation · 02 Sept 2024, 22:01 UTC
I am designing a Fastify (v4/v5) API where most endpoints accept small JSON payloads, but one upload route needs to accept bodies of several megabytes. The documented bodyLimit option can be set at server instantiation and also per route, and exceeding the limit produces a 413 response.
What I cannot determine from the documentation alone is how the two levels interact in edge cases. Specifically, whether a route-level bodyLimit completely replaces the global value for that route, or whether some stricter of the two is applied. I am also unsure whether the limit is enforced identically for every parsed content type (JSON, URL-encoded, text) or only for the built-in parsers, and what happens to the limit when a custom content-type parser is registered for a route.
A secondary concern is operational: if the global limit is raised for one large-payload route, does that meaningfully increase memory-exhaustion risk for concurrent requests on other routes, or does the per-route override avoid that entirely?
bodyLimit fully override the global value, and is this guaranteed across Fastify v4 and v5?30775 reputation · 03 Sept 2024, 08:37 UTC
1. Does a route‑level bodyLimit fully override the global value? Yes. In both Fastify v4 and v5 the value supplied on a route is used exclusively for that route. The framework does not compare the two values; it discards the global setting for that request path.
2. When is the limit enforced and does it apply to custom parsers? The check happens on the raw request body before any content‑type parser runs. All built‑in parsers (JSON, url‑encoded, text) honour the same threshold. If you register a custom parser that pulls the body from the stream outside Fastify’s interception layer, the limit may be bypassed unless the parser itself respects the bodyLimit value.
3. Is a route‑specific override the recommended pattern? Absolutely. Raising the global limit increases memory pressure for every concurrent request. Using a per‑route override confines the larger allowance to the upload endpoint, keeping other routes safe.
effectiveLimit = route.bodyLimit if defined, otherwise server.bodyLimit.effectiveLimit. If exceeded, Fastify aborts the request and returns 413 Payload Too Large before any parser runs.req.headers["content-length"] or req.rawBodyLength.bodyLimit: 20 * 1024 * 1024 (or whatever size you need).bodyLimit at a conservative value, e.g., 1 * 1024 * 1024.req.rawBodyLength against the route’s bodyLimit and aborts with a 413 if necessary.preHandler hook that logs the effective limit and the received body size for audit purposes.To be certain that your custom content‑type parser respects the limit, run a small test:
await fastify.inject({
method: 'POST',
url: '/upload',
payload: Buffer.alloc(25 * 1024 * 1024), // 25 MB
headers: { 'content-type': 'application/octet-stream' }
}).then(res => console.log(res.statusCode));
If you receive a 413, the parser is compliant. If not, you must add an explicit size check inside the parser.
Do you register any custom content‑type parsers that read the body stream outside Fastify’s built‑in pipeline?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.