Understand Nginx location matching order

Trace exact, prefix, and regex location selection, including the limits of the usual flat-configuration rule.

Best practices
Illustration of server operations and request logs

For locations at the same level, start with exact matches, remember the longest matching prefix, then consider regex locations unless that longest prefix has ^~. Query-string parameters are not part of location matching.

Follow the selection sequence

  1. An = location that matches the normalized URI ends the search.
  2. Nginx finds the longest matching prefix, including prefixes marked ^~.
  3. If that prefix has ^~, same-level regex checks are skipped.
  4. Otherwise, regex locations are checked in configuration order; the first match wins.
  5. If no regex matches, the remembered prefix is used.
Form Meaning
location = /a Exact normalized URI match.
location ^~ /a Prefix that skips regex checks when it is the longest matching prefix at that level.
location ~ \.php$ Case-sensitive regex.
location ~* \.(jpg|png)$ Case-insensitive regex.
location /a Ordinary prefix, subject to later regex selection.

A ^~ prefix is not globally stronger than every longer ordinary prefix. URI normalization, such as percent decoding and path cleanup, also means an exact match is not a byte comparison of the raw request target.

Trace a flat example

These diagnostic locations can be placed inside a test server:

location /              { return 200 "root\n"; }
location /images/       { return 200 "images\n"; }
location ^~ /static/    { return 200 "static\n"; }
location ~ \.css$       { return 200 "css\n"; }
location = /favicon.ico { return 200 "favicon\n"; }
URI Selected location
/favicon.ico Exact favicon location.
/static/style.css The longest prefix is ^~ /static/; the CSS regex is skipped.
/images/style.css The CSS regex overrides the ordinary /images/ prefix.
/images/cat.jpg The /images/ prefix remains selected.

Regexes are tested in their listed order, not ranked by apparent specificity. Put a necessary narrow regex before a broader one, and test the overlapping paths.

Treat nesting and internal redirects separately

Nested locations make the flat shorthand incomplete. Nginx descends into the selected prefix's nested locations, and outer-level regex checks can still matter as the search returns. In particular, a nested ^~ does not automatically shield a request from every ancestor's regex. Exact and named locations also have nesting restrictions. Prefer a flat layout when it expresses the route clearly; use a route matrix when nesting is necessary.

An index, try_files fallback, or rewrite can initiate an internal redirect and a new location search. The first selected location may therefore not be the one that generates the final response.

FAQ

Does root behave like alias?

No. root appends the URI to a filesystem prefix. A prefix alias replaces the matched location portion; regex aliases require their own capture-based mapping. Check the actual filesystem path independently of route selection.

How can I see which location handled a request?

In a test configuration, use distinct responses as above. A temporary add_header X-Location "images" always; is another option, but header inheritance can change when you add it. Remove diagnostic markers after testing. Debug logging is available on a suitably built Nginx installation.

Can collected access logs show the chosen backend?

Only if the format includes the required variables, such as $upstream_addr, plus a useful route marker where appropriate. DataKit log collection cannot reconstruct a route field that Nginx never recorded. Compare exact, prefix, regex, and internally redirected requests after each change.

Reference: Nginx location directive.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting