Nginx Location Block Matching Rules

Understand Nginx location block matching priority including exact match, preferential prefix, regex, and generic prefix with practical routing examples.

Routing

Detailed Explanation

The location directive is one of the most important and frequently misunderstood concepts in Nginx configuration. It determines how Nginx processes requests based on the URI path, and understanding the matching priority is essential for correct routing behavior.

Location Types and Priority

Nginx evaluates location blocks in a specific order of priority, regardless of the order they appear in the configuration file:

  1. Exact match (=): Highest priority. Matches the URI exactly and stops searching immediately.
  2. Preferential prefix (^~): If this prefix matches, Nginx skips all regex evaluation.
  3. Regex (~ case-sensitive, ~* case-insensitive): Evaluated in the order they appear in the file.
  4. Prefix match (no modifier): The longest matching prefix wins, but a regex match can override it.
location = /exact { }          # Only matches /exact
location ^~ /images/ { }       # Prefix match, skips regex
location ~ \.php$ { }          # Case-sensitive regex
location ~* \.(jpg|png)$ { }   # Case-insensitive regex
location /documents/ { }       # Standard prefix
location / { }                 # Catch-all fallback

How Matching Works Step by Step

When a request arrives, Nginx first checks all prefix locations (both regular and preferential) and remembers the longest match found. If the longest match uses the ^~ modifier, regex evaluation is skipped entirely. Otherwise, Nginx proceeds to check regex locations in their configuration file order. If any regex matches, it takes precedence over the remembered prefix match. If no regex matches, the longest prefix match is used.

Common Configuration Patterns

Serve static files directly while proxying everything else:

location ~* \.(css|js|jpg|png|gif|ico|svg|woff2)$ {
    root /var/www/static;
    expires 30d;
}

location / {
    proxy_pass http://backend;
}

API versioning with separate backends:

location /api/v1/ {
    proxy_pass http://api_v1_backend;
}

location /api/v2/ {
    proxy_pass http://api_v2_backend;
}

Nested Locations

Locations can be nested within each other. Inner locations inherit directives from outer locations unless they are explicitly overridden:

location /app/ {
    proxy_pass http://backend;

    location /app/static/ {
        alias /var/www/static/;
    }
}

Debugging Location Matching

To debug which location block is handling a specific request, add a custom response header in each location block:

location / {
    add_header X-Debug-Location "root-catchall" always;
}

Then inspect the response headers with curl -I to confirm the correct block is being matched for each request path.

Use Case

You are configuring complex Nginx routing rules and need to understand which location block handles each request to avoid unexpected behavior with overlapping patterns.

Try It — Nginx Config Generator

Open full tool