Summary
Serving a React SPA and its API under one domain, with NGINX routing by path, is a common and reasonable choice — no CORS configuration, one SSL certificate, one public surface. It also means the reverse-proxy config is no longer an incidental detail. It's the single piece of infrastructure both the frontend and the API depend on to be reachable at all.
Problem
The alternative — separate subdomains for frontend and backend — keeps the two independent: a routing mistake on one doesn't touch the other, at the cost of CORS handling and two certificates to manage. Collapsing both behind one NGINX config removes that overhead, but it also removes the isolation. A misconfigured rewrite rule doesn't degrade one surface; it can take down the path routing for both at once.
Discussion
That failure mode isn't hypothetical — it's what a rewrite loop looks
like in production: NGINX matches a request, rewrites it, and the
rewritten request matches the same rule again, looping until the request
times out or the worker gets pinned. Once it happens, the fix isn't
guessing at the frontend or backend code — it's reading the NGINX config
itself, tracing exactly which location block and rewrite directive
the request is hitting and why it isn't terminating.
The broader pattern is what self-managed infrastructure means in practice: there's no managed platform layer absorbing this. Permission errors on the host, the reverse-proxy config, database constraints — all of it is a production surface you diagnose directly, because nothing sits between the deployment and you to catch it first. Unified routing under one NGINX config is a reasonable simplification. It's a simplification that requires treating that config with the same care as application code, not as a one-time setup step.
Key Takeaways
- Unifying a frontend and API under one reverse-proxy config trades isolation for operational simplicity — know which one you're choosing.
- A rewrite loop is diagnosed by reading the proxy config's
locationandrewriterules directly, not by inspecting application code. - On self-managed infrastructure, every layer — permissions, proxy config, schema constraints — is a production surface with no managed platform absorbing the failure first.