Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Nginx Location Directive: Prefix, Regex, and Priority

Sean

Platform Writer

Jul 05, 2026
6 min read

Nginx location directive matches incoming request URIs and routes them. Three modifier types: exact (=), prefix (no modifier), regex (~ for case-sensitive, ~* for case-insensitive). Priority: = exact match wins, then ^~ longest prefix, then regex, then longest prefix. The team that uses = for health checks and prefix for general routing has the right pattern.

Nginx Location Directive: Prefix, Regex, and Priority

Table of contents

The location syntax

location [modifier] pattern {
    # config
}

Modifiers:

  • =: exact match (highest priority).
  • ^~: prefix match, no regex check.
  • ~: case-sensitive regex.
  • ~*: case-insensitive regex.
  • (none): prefix match.

Priority order

Per the Nginx docs:

  1. Exact match = (highest priority).
  2. ^~ longest prefix - if matched, no regex checked.
  3. Longest matching prefix (without ^~).
  4. First matching regex (~ or ~*).

The team that knows the priority has predictable routing.

Examples

# Exact match for health check
location = /healthz {
    return 200 'ok';
}

# Prefix: anything starting with /api/
location /api/ {
    proxy_pass http://backend;
}

# Case-sensitive regex for image files
location ~ \.(gif|jpg|png)$ {
    expires 30d;
}

# Case-insensitive regex
location ~* \.(JPG|PNG)$ {
    expires 30d;
}

# ^~ prefix (no regex check for these)
location ^~ /static/ {
    root /var/www;
}

Common pitfalls

  1. Greedy regex: location ~ /api/(.*) matches /api/, /api/foo, /api/foo/bar. The team that anchors with ^ and $ has precise matches.
  2. Regex overhead: regex location blocks run on every request. The team that uses prefix where possible has faster routing.
  3. = exact doesn’t match query strings. The team that needs query-string matching uses regex.

The named location

location @fallback {
    proxy_pass http://backend_upstream;
}

Referenced via try_files or error_page. The team that uses named locations has clean fallback routing.

Common patterns

# React SPA - serve index.html for any non-asset
location / {
    try_files $uri /index.html;
}

# API reverse proxy
location /api/ {
    proxy_pass http://api_backend;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

# Static assets with long cache
location ~* \.(js|css|png|jpg|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Testing location matches

The team that needs to debug which location matches a URL:

# Show the matched config
nginx -T | grep -A 5 "location /problem-url"

Or use the nginx location matcher tools to simulate priority.

FAQ

What’s the priority between prefix and regex location?

Exact match (highest), then ^~ longest prefix (skips regex), then longest prefix, then first matching regex.

Why isn’t my regex location matching?

Either wrong regex syntax, or a ^~ prefix matched first. The team that uses ^~ on /api/ has the regex on /api/.* never run.

Can I have multiple location blocks for the same prefix?

Yes - different modifiers or patterns. The team that uses = /healthz plus /api/ has separate routing for health and API.

What about the trailing slash?

Location pattern is matched against the normalized URI. location /api/ matches URIs starting with /api/. The team that uses trailing slash on prefixes is consistent.

How do I match query strings?

Use if ($arg_key = value) or include in regex. The team that uses query strings has to handle this case explicitly.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#nginx#location#config#dev-infra