100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
DevOps

Locations and Matching Rules

How Nginx's location block matching algorithm actually works — prefix, exact, and regex modifiers, and the precedence order that trips up most misconfigurations.

ConfigurationIntermediate9 min readJul 10, 2026
Analogies

How Nginx Chooses a location Block

Inside a server block, location directives map URI paths to specific handling logic — where to look for files, which upstream to proxy to, or which headers to set. Nginx doesn't evaluate location blocks top-to-bottom like a firewall ruleset; instead it runs a two-phase algorithm: it first finds the longest matching prefix among all non-regex locations, then checks regex locations (~ and ~*) in the order they're written, and a regex match overrides the prefix match unless the prefix location was declared with the ^~ modifier to short-circuit regex checking entirely.

🏏

Cricket analogy: It's like a fielding captain first placing fielders by general zone (longest prefix, e.g. covers) before making a specific tactical regex-like adjustment such as a short leg for a particular batsman, unless the captain locks the field with a fixed plan (^~) that overrides further tweaks.

Prefix, Exact, and Regex Location Modifiers

The plain prefix form location /api/ { ... } matches any URI beginning with /api/ and Nginx keeps the longest such match found. location = /health { ... } requires an exact URI match with no trailing characters, which is the fastest possible match and commonly used for health-check endpoints. Case-sensitive regex uses ~ (location ~ \.php$ { ... }) while case-insensitive regex uses ~* (location ~* \.(jpg|png|gif)$ { ... }), and both are evaluated in source order the moment Nginx moves into the regex-matching phase, stopping at the first one that matches.

🏏

Cricket analogy: It's like the difference between a general fielding restriction for the powerplay overs (prefix match) versus a very specific no-ball review rule (exact match) that applies to one delivery only and gets checked instantly.

The ^~ Modifier and Common Pitfalls

The ^~ modifier tells Nginx: if this prefix location is the longest matching prefix, stop immediately and skip the regex-matching phase entirely, even if a later regex would otherwise match more specifically. This is frequently used to protect a directory like location ^~ /static/ { ... } from being intercepted by a broad regex rule such as location ~* \.(css|js)$ { ... } intended for a different purpose. A common pitfall is assuming location blocks are checked strictly top-to-bottom; forgetting the prefix-then-regex algorithm leads to configs where a seemingly 'later' rule silently wins.

🏏

Cricket analogy: It's like a captain declaring a fixed field placement for the death overs that no bowler-specific tactical adjustment is allowed to override, even if a normally sharper plan would apply later in the over.

nginx
server {
    listen 80;
    server_name example.com;

    # Exact match wins instantly for health checks
    location = /health {
        return 200 "ok";
        add_header Content-Type text/plain;
    }

    # ^~ stops regex matching from intercepting static assets
    location ^~ /static/ {
        root /var/www/example.com;
        expires 30d;
    }

    # Case-insensitive regex for image extensions elsewhere
    location ~* \.(jpg|jpeg|png|gif|ico)$ {
        root /var/www/example.com;
        expires 7d;
    }

    # Longest matching prefix for the API
    location /api/ {
        proxy_pass http://backend_upstream;
        proxy_set_header Host $host;
    }
}

Reload with nginx -t && nginx -s reload after changing location blocks, and test ambiguous paths with curl -v http://localhost/static/app.js to confirm which block actually served the request via response headers or logging.

location blocks are NOT evaluated top-to-bottom. Nginx finds the longest matching prefix first, then only checks regex locations afterward — and a regex match beats a plain prefix match unless ^~ is used. Assuming file order controls precedence is one of the most common Nginx misconfiguration bugs in production.

  • location blocks are matched by a longest-prefix-then-regex algorithm, not simple top-to-bottom order.
  • = performs an exact match and resolves fastest, ideal for health-check endpoints.
  • Plain prefix locations match the longest matching path; ^~ stops Nginx from then checking regex locations.
  • ~ is case-sensitive regex, ~* is case-insensitive regex, both evaluated in source order after prefix matching.
  • Regex locations override a plain prefix match unless the prefix location uses ^~.
  • Use curl -v and access logs to empirically confirm which location actually handled an ambiguous request.

Practice what you learned

Was this page helpful?

Topics covered

#DevOps#NginxStudyNotes#LocationsAndMatchingRules#Locations#Matching#Rules#Nginx#StudyNotes#SkillVeris#ExamPrep