Skip to main content

Advanced Location Block Matching

Now that you've mastered the fundamentals of Nginx configuration, it's time to dive deeper into one of the most powerful features: advanced location block matching. While you've already worked with basic location directives, understanding the nuances of matching priority, regex patterns, and optimization techniques will elevate your Nginx configuration skills to an expert level.

Learning Goals

  • Understand location block matching priority and precedence
  • Master regular expression location blocks
  • Learn named location blocks and their use cases
  • Optimize location matching for performance
  • Apply advanced matching in real-world scenarios

Location Block Matching Fundamentals

Nginx processes location blocks in a specific order, not necessarily the order they appear in your configuration file. Understanding this priority system is crucial for writing predictable configurations.

Matching Priority Rules

Nginx evaluates location blocks in this order:

  1. Exact matches (=) - highest priority
  2. Prefix matches (^~) - non-regex priority
  3. Regular expressions (~, ~*) - first match wins
  4. Standard prefixes - longest match wins
nginx.conf
server {
listen 80;
server_name example.com;

# 1. Exact match (highest priority)
location = /images/logo.png {
return 301 /static/logo-new.png;
}

# 2. Case-sensitive regex
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi.conf;
}

# 3. Case-insensitive regex
location ~* \.(jpg|jpeg|png|gif)$ {
expires 1y;
add_header Cache-Control "public";
}

# 4. Standard prefix match
location /static/ {
alias /var/www/static/;
}

# 5. Catch-all
location / {
proxy_pass http://backend;
}
}

Regular Expression Location Blocks

Regular expression location blocks provide powerful pattern matching capabilities. Use ~ for case-sensitive and ~* for case-insensitive matching.

Advanced Regex Patterns

regex-locations.conf
server {
listen 80;
server_name api.example.com;

# Match API version endpoints (v1, v2, etc.)
location ~ ^/api/v(\d+)/ {
set $api_version $1;
proxy_pass http://api-backend-v$api_version;
}

# Match user profiles with numeric IDs
location ~ ^/user/(\d+)/profile$ {
proxy_pass http://user-service/user/$1;
}

# Case-insensitive file type matching
location ~* \.(pdf|docx?|xlsx?|pptx?)$ {
add_header X-File-Type "Document";
root /var/www/documents;
}

# Complex path matching with exclusions
location ~ ^/admin/(?!login|logout).+$ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://admin-backend;
}
}
tip

Use regex location blocks sparingly as they're processed sequentially and can impact performance. For common file extensions, consider using map directives for better performance.

Named Location Blocks

Named location blocks (@name) don't process client requests directly but can be targeted by other directives like error_page, try_files, and internal redirects.

named-locations.conf
server {
listen 80;
server_name app.example.com;

# Main application handler
location / {
try_files $uri $uri/ @backend;
}

# API endpoint handler
location /api/ {
try_files $uri @api_backend;
}

# Named location for main backend
location @backend {
proxy_pass http://app-backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# Named location for API backend
location @api_backend {
proxy_pass http://api-backend;
proxy_set_header X-Real-IP $remote_addr;
}

# Error handling with named locations
location @error_404 {
return 404 '{"error": "Not Found", "code": 404}';
}

location @maintenance {
return 503 '{"error": "Service Temporarily Unavailable"}';
add_header Retry-After 3600 always;
}

error_page 404 @error_404;
error_page 502 503 @maintenance;
}

Performance Optimization Techniques

Using Prefix Matching with ^~

The ^~ modifier gives a prefix match higher priority than regular expressions, improving performance for frequently accessed paths.

optimized-matching.conf
server {
listen 80;
server_name assets.example.com;

# High-priority static assets (skips regex evaluation)
location ^~ /static/js/ {
gzip_static on;
expires max;
add_header Cache-Control "public, immutable";
root /var/www/assets;
}

# High-priority CSS assets
location ^~ /static/css/ {
gzip_static on;
expires 1h;
root /var/www/assets;
}

# Media files with regex (lower priority but necessary for pattern matching)
location ~* \.(webp|avif)$ {
expires 1y;
add_header Vary Accept;
root /var/www/assets;
}
}

Map Directives for Efficient Matching

For complex matching logic, map directives can be more efficient than multiple regex location blocks.

map-directive.conf
# Define mapping outside server block
map $uri $content_type_override {
default "";
~*\.min\.(css|js)$ "text/plain";
~*\.(woff2?|ttf|eot)$ "font/woff2";
}

server {
listen 80;
server_name example.com;

location / {
# Apply the mapped content type if defined
if ($content_type_override) {
add_header Content-Type $content_type_override;
}

root /var/www/html;
try_files $uri $uri/ =404;
}
}

Real-World Advanced Scenarios

Multi-Tenant Application Routing

multi-tenant.conf
server {
listen 80;
server_name ~^(?<tenant>[a-z0-9-]+)\.example\.com$;

# Tenant-specific static assets
location ^~ /static/ {
root /var/www/tenants/$tenant/assets;
try_files $uri @fallback_static;
}

# Tenant API endpoints
location ~ ^/api/(v1|v2)/(.+)$ {
proxy_pass http://$tenant-api-backend/$1/$2;
proxy_set_header X-Tenant $tenant;
}

# Tenant application
location / {
proxy_pass http://$tenant-app-backend;
proxy_set_header X-Tenant $tenant;
proxy_set_header Host $host;
}

# Fallback for missing tenant assets
location @fallback_static {
root /var/www/common/assets;
}
}

A/B Testing with Location Matching

ab-testing.conf
split_clients "${remote_addr}${http_user_agent}" $ab_test_group {
50% "group_a";
50% "group_b";
}

server {
listen 80;
server_name example.com;

# A/B test for homepage
location = / {
if ($ab_test_group = "group_a") {
proxy_pass http://app-version-a;
}
if ($ab_test_group = "group_b") {
proxy_pass http://app-version-b;
}

# Default fallback
proxy_pass http://app-production;
}

# Rest of the application
location / {
proxy_pass http://app-production;
}
}
warning

Be cautious with if blocks in location contexts. They can have unexpected side effects due to Nginx's processing phases. Use them primarily for simple checks and redirects.

Common Pitfalls

  • Regex evaluation order: Regular expressions are evaluated in configuration file order, not by specificity
  • Performance impact: Excessive regex location blocks can significantly slow down request processing
  • Case sensitivity confusion: Mixing ~ and ~* can lead to unexpected matching behavior
  • Location precedence misunderstanding: Exact matches (=) always win, even if they appear after other matches
  • Overly complex regex: Hard-to-read patterns make debugging difficult and can introduce security issues
  • Missing fallback handlers: Not providing catch-all locations can result in unexpected 404 errors
  • Proxy pass in named locations: Named locations can't contain root, alias, or proxy_pass without additional configuration

Summary

Advanced location block matching is essential for building sophisticated Nginx configurations. Remember these key points:

  • Understand matching priority: exact → prefix (^~) → regex → standard prefix
  • Use named locations for error handling and internal routing
  • Optimize performance with prefix matches for high-traffic paths
  • Leverage map directives for complex conditional logic
  • Apply these techniques to real-world scenarios like multi-tenancy and A/B testing

Mastering these concepts will help you create more efficient, maintainable, and powerful Nginx configurations.

Quiz

Nginx Location Matching and Priority Rules

What is the highest priority type of location block match in Nginx?

Question 1/5