nginx proxy_pass leads to 404 Not Found page
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When proxy_pass leads to a 404 Not Found, the problem is often not Nginx itself. The request is usually reaching the upstream application with a path the application does not recognize. That mismatch commonly comes from the interaction between location matching and the exact form of the proxy_pass URL.
The most important detail is the trailing slash. In Nginx, a trailing slash on proxy_pass changes how the request URI is rewritten before it is sent upstream.
The Trailing Slash Rule
Consider this configuration:
With the trailing slash on proxy_pass, Nginx replaces the matched /api/ prefix with / before forwarding the request. So a request for /api/users becomes /users on the upstream server.
Now compare it with this:
Without the trailing slash, the original URI is forwarded as-is. A request for /api/users stays /api/users on the upstream.
If your application expects /users but receives /api/users, it returns 404. If it expects /api/users but receives /users, it also returns 404.
Diagnose Where the 404 Comes From
Before editing configuration blindly, confirm whether the 404 is generated by Nginx or by the upstream service.
Useful checks include:
If one upstream path works and the other fails, you have identified the rewrite mismatch immediately.
You should also inspect logs:
An upstream framework log is often even more useful because it shows the exact path the application received.
A Common Correct Pattern
If your public route is /api/... but the upstream app serves routes without that prefix, use:
If the upstream app already includes /api/... in its route definitions, remove the trailing slash from proxy_pass so the prefix is preserved.
Avoid Manual Rewrite Confusion
It is possible to combine rewrite directives with proxy_pass, but that often makes troubleshooting harder than necessary. In many cases, choosing the correct trailing-slash form is enough.
If you do need explicit rewriting, keep it obvious:
That can work, but it adds one more moving part. Simpler configurations are easier to reason about and maintain.
Other Reasons for Upstream 404
Path rewriting is the most common cause, but not the only one. A proxied request can still return 404 if:
- the upstream app is listening on a different port
- the upstream virtual host depends on the
Hostheader - the location block does not match the request you think it matches
- a framework router only accepts certain methods
That is why direct curl tests against the upstream port are so useful. They separate routing problems from proxy configuration problems.
Common Pitfalls
The biggest pitfall is not realizing that proxy_pass http://backend/; and proxy_pass http://backend; do different things. That one character changes the forwarded URI.
Another issue is testing only through Nginx and never calling the upstream directly. Without direct upstream tests, it is hard to tell whether the route exists at all.
People also forget that a 404 can be application-generated. If Nginx is configured correctly but the backend router does not define the forwarded path, the result is still 404.
Finally, after editing Nginx, always validate and reload the config:
Summary
- A
404afterproxy_passis often caused by URI rewriting rather than by Nginx failing to proxy. - The trailing slash on
proxy_passcontrols whether the matched location prefix is replaced. - Test the upstream path directly to confirm what route the backend actually serves.
- Add standard proxy headers so the upstream receives the expected request context.
- Prefer simple
locationandproxy_passcombinations before adding separate rewrite rules.

