Skip to content

perf: cache parsed request queries - #7463

Closed
itsanickname-beep wants to merge 1 commit into
expressjs:masterfrom
itsanickname-beep:perf/cache-query
Closed

itsanickname-beep wants to merge 1 commit into
expressjs:masterfrom
itsanickname-beep:perf/cache-query

Conversation

@itsanickname-beep

Copy link
Copy Markdown

Summary

Memoize req.query after the first parse for the lifetime of a request. Applications that read the query object in multiple middleware layers no longer rerun the configured parser (including the more expensive extended qs parser). Disabled query parsing retains its existing behavior.

Performance audit: 10 opportunities

  1. Memoize req.query parsing (implemented here): eliminate repeated parser work per request; high request-path impact and a small isolated change.
  2. Memoize req.accepts*() negotiation results when the same request and candidate list are queried repeatedly.
  3. Cache parsed Accept header state on the request instead of constructing a new accepts instance for each negotiation call.
  4. Cache trusted proxy lookup results for req.protocol, req.host, req.ip, and req.ips within a request.
  5. Avoid repeated app.get() setting lookups in hot response paths by resolving stable settings once per request.
  6. Reuse a normalized view-root array in View instead of concatenating this.root on every lookup.
  7. Reduce synchronous filesystem probes for missing views by caching negative view lookups during a render cycle.
  8. Avoid repeated MIME normalization in res.format() when the same content types are negotiated more than once.
  9. Optimize object-form response header setting to call setHeader directly after normalization rather than recursively dispatching through res.set.
  10. Add route/middleware dispatch benchmarks to identify whether path matching or middleware traversal dominates high-route-count applications before optimizing the router boundary.

Validation

  • Added a regression test proving a custom query parser runs once and returns the same request-local object on repeated access.
  • git diff --check passes.
  • Node/npm are not installed in this environment, so the Mocha and ESLint commands could not be run here.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@krzysdz

krzysdz commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Not caching req.query is a deliberate decision - it should always reflect the current req.url value.

You can find more details in: #6042 (comment)

Duplicate of #6042

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants