Here's something that'll make you waste an afternoon if you're not careful.
You're setting up nginx as a reverse proxy. You have a location block, and inside it you use proxy_pass to forward to your backend. Simple enough.
But there's this one detail about trailing slashes that changes everything, and it's not obvious until you've been burned by it.
The Two Behaviors
With a trailing slash:
location /api/ {
proxy_pass http://backend/;
}
A request to /api/users becomes /users at the backend. The /api/ prefix gets stripped.
Without a trailing slash:
location /api/ {
proxy_pass http://backend;
}
A request to /api/users stays /api/users at the backend. The full path is preserved.
That's it. One slash changes whether your backend sees /users or /api/users.
A Simple Mental Model
Think of it this way:
- Slash present = "replace the matched location with this"
- No slash = "prepend this to the existing path"
With the slash, nginx treats it as "strip the prefix and replace with what's after the slash." Without it, it just passes through unchanged.
When This Matters
Most of the time you want the slash-stripping behavior. Your backend doesn't need to know it's mounted at /api/ — it just wants /users.
But sometimes your backend expects the full path. Maybe it's serving multiple apps and uses the prefix to route internally. Then you leave the slash off.
When to Use rewrite Instead
If you need something more complex — like renaming paths or doing conditional routing — don't try to hack it with proxy_pass slashes. Just use rewrite:
location /api/ {
rewrite ^/api/(.*)$ /v2/$1 break;
proxy_pass http://backend;
}
Now /api/users becomes /v2/users at the backend. Clear, explicit, no magic.
The Takeaway
When you're setting up a reverse proxy:
- Check if your backend expects the prefix or not
- Add or remove the trailing slash accordingly
- If you need anything fancier, use
rewriteinstead of trying to be clever
It's one character. But it'll cost you two hours of debugging if you get it wrong.
Top comments (1)
One related gotcha that catches people: the trailing slash replacement silently stops working when the proxy_pass target contains variables, like when you resolve the backend through a resolver. In that case nginx passes the request URI as received and the slash rule no longer applies, so you have to rewrite the path explicitly instead. Good write-up, this really is a one character change that can cost hours.