This episode breaks down the five location syntax types in NGINX and the location selection priority rules, so you know exactly why a URI is matched to a particular block.

The location block is the routing brain of NGINX. Every incoming request must be matched to the most appropriate location, and NGINX has very specific priority rules. This Episode 4 breaks down the five location syntax types and the order in which they're evaluated.
Many configuration bugs start with a misunderstanding of location: .php config that never executes, static assets caught by the wrong block, or regex that's never used. After this episode, you'll understand why that happens and how to prevent it.
The = modifier creates an exact match. It's the fastest and has the highest priority:
location = /favicon.ico {
log_not_found off;
}location = /favicon.ico only matches the URI /favicon.ico, not /favicon.ico/ or /favicon.ico.png. Use exact matches for URIs that must be handled very quickly, like favicons and 404 pages.
The ^~ modifier marks a prioritized prefix match: if a URI matches this prefix, NGINX stops searching and never checks regex:
location ^~ /assets/ {
root /var/www/site;
expires 30d;
}The ~ modifier matches a regex pattern case-sensitively, while ~* matches case-insensitively:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 30d;
add_header Cache-Control "public";
}location ~ \.php$ catches PHP files, and location ~* catches static assets with any extension regardless of letter case.
Without a modifier, this is an ordinary prefix match. NGINX will remember the longest matching prefix:
location /docs/ {
root /var/www;
}When a request arrives, NGINX evaluates locations in the following order:
= modifier — if it matches, it's used immediately.^~ modifier — if it matches and is the longest, it's used and the search stops.~ and ~*) — evaluated in the order they're written; the first regex that matches is used immediately.The key that's often forgotten: regex beats standard prefix, but loses to exact match and preferential prefix match. Let's look at a concrete example.
Consider the following configuration with a request for GET /assets/img/logo.png:
server {
listen 80;
server_name example.com;
location /assets/ {
root /var/www/site;
}
location ~* \.(png|jpg|css|js)$ {
expires 30d;
}
}The request /assets/img/logo.png matches the standard prefix /assets/, and also matches the regex ~* \.(png|jpg|css|js)$. Because regex is evaluated after prefix, NGINX picks the regex, so the expires 30d header applies. If you want static assets served without regex, add ^~:
location ^~ /assets/ {
root /var/www/site;
expires 30d;
}Now ^~ wins because it has higher priority than regex. This is how NGINX decides which block gets used.
location / matches every URI, so it always acts as the last-resort fallback.error_page target if that target maps to another location that also matches.To see the full configuration NGINX will apply, run:
sudo nginx -T | lessnginx -T merges all configuration files after the include process. You can check whether the location you wrote actually sits in the expected server block.
Check the access log to see the status of every request and confirm routing behaves as expected:
sudo tail -f /var/log/nginx/access.logThe combination of nginx -T and the access log is enough to crack almost any location routing mystery.
Episode 4 equipped you with NGINX's routing logic: five location types with different modifiers, the priority order from exact match to standard prefix, and how regex beats standard prefix unless ^~ comes into play.
Key takeaways:
location = /path is the fastest exact match.location ^~ /path/ prioritizes the prefix and stops the regex search.~ is case-sensitive regex, ~* is case-insensitive regex, both are first match.= then ^~ then regex then longest prefix.nginx -T and the access log are the best routing debugging tools.In the next episode we'll discuss rewrite rules, redirects, and URL manipulation — the difference between return and rewrite, 301 versus 302 statuses, flags on rewrite, and the try_files pattern for single page application routing. Get ready, because this is where URLs start "fighting" with NGINX.