Tengine location matching priority explained

2026-09-29

AdSense Slot

“My location block looks right but the request goes somewhere else.” Every Tengine user hits this eventually. The culprit is almost always location matching priority — Tengine does not use the first matching block, and it does not use the longest one for everything. Here is the actual rule, in the order Tengine evaluates it.

The matching algorithm, simplified

  1. First, Tengine finds the longest matching prefix location (plain, non-regex).
  2. If that prefix location uses the ^~ modifier, it wins immediately — regex is never checked.
  3. Otherwise, Tengine then checks all regex locations (~ and ~*) in config order; the first matching regex wins.
  4. If no regex matches, the longest prefix location from step 1 wins.
  5. An exact match with = beats everything for that exact URI.

Example that shows the rule

location = /exact { return 200 "exact\n"; }        # exact URI only
location ^~ /api/ { proxy_pass http://backend; }    # prefix, blocks regex
location ~* \.(png|jpg)$ { return 200 "img\n"; }    # regex, checked in order
location / { return 200 "root\n"; }                 # longest-prefix fallback

The mistakes I keep seeing

Summary

Longest prefix first, then first regex in order, with ^~ and = as shortcuts. Once this clicks, most “rewrite not working” mysteries disappear — which is exactly the topic of my rewrite troubleshooting guide.

AdSense Slot