AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

`Next Start` Built-In Compression Never Applies To Route Handlers (Including Metadata Routes) — Sitemap.Xml Served Uncompressed

In Next.js 16.2.10, when using `next start`, page renders are correctly compressed by the built-in `compression` middleware, but all Route Handler responses (including static/prerendered metadata routes and dynamic route handlers) are sent without any `Content-Encoding`. This occurs even when the response body is well above the 1KB compression threshold and the content type is compressible (e.g., `application/xml`). The issue violates the official documentation's promise that Next.js compresses "rendered content and static files" by default, leading to wasted bandwidth and degraded performance for sitemaps, JSON APIs, and other large Route Handler responses in self-hosted environments.

highConfidence 85%Next.jsAffected V16.2.10

Origin Analysis

In `server/lib/router-server.js`, the `requestHandlerImpl` function invokes the `compression` middleware for every request by calling `compress(req, res, () => {})`. This middleware works by modifying the `res` object's methods (e.g., `writeHead`, `write`, `end`) to inject compression. However, Route Handler responses are written through a different path that bypasses these modified methods—likely because Route Handlers operate on a different response object (or directly on the original `res` without the middleware's patches). The observed header casing difference (page responses use `Content-Type` while Route Handler responses use lowercase `content-type`) confirms that Route Handler responses are not going through the `compression` middleware's wrappers, leaving them uncompressed.
1. Create a Next.js 16.2.10 project with a page route (`app/page.js`), a metadata route (`app/sitemap.js`, body >1KB), and a force-dynamic route handler (`app/d.xml/route.js`, body >1KB). 2. Run `npm run build && npm run start`. 3. Execute `curl -s -H 'Accept-Encoding: gzip, br' -D - -o /dev/null http://127.0.0.1:3000/` and observe `Content-Encoding: gzip` in the response headers. 4. Execute the same command for `/sitemap.xml` and `/d.xml`. The response headers will lack `Content-Encoding` and all headers will be lowercase, indicating the compression middleware was bypassed.

Fixing Code Block

Edge Case Audit

Using a custom server may disable certain Next.js optimizations and features that rely on `next start` (e.g., Turbopack integration, automatic port handling, graceful shutdown). It adds an external dependency (`compression`) and requires manual process management in production. If the official fix is released, remove this workaround and revert to `next start`. Rollback: delete `server.js`, remove the `compression` package, and restore the original `next start` command.

Ecosystem Topology