A Small Fix for a Big Issue: OpenResty, IPv6, and the 90-Second Timeout Mystery
- shrikkanthb
- Jul 31
- 2 min read
Updated: Aug 5
Recently, while working on a .NET-based UI application deployed with OpenResty as the HTTPS reverse proxy, I ran into a strange issue:The UI would just hang on loading, and after 90 seconds, it would reload automatically or timeout.
At first glance, there was nothing obviously wrong — the backend was up, OpenResty was running, and everything seemed configured correctly.
But something wasn’t right.
🔍 The Problem
When I checked the browser’s network tab, requests were just stuck in the “loading” state. No error messages. No instant failures.Just... a long wait followed by a timeout.
Looking at the OpenResty logs, I found this line:
upstream timed out (110: Connection timed out) while connecting to upstream, client: 99.89.71.217, server: staging.elliedx.com, request: "POST /lapi/json/reply/RetrieveDaOrders HTTP/1.1", upstream: "http://[::1]:5000/lapi/json/reply/RetrieveDaOrders", host: "staging.elliedx.com"
Wait — what’s http://[::1]:5000 doing there?
That’s IPv6 localhost.
But my application DNS and networking were all using IPv4.
Here’s a screenshot from one of our Hetzner servers showing that both IPv4 and IPv6 were assigned during server creation:

🧠 The Root Cause
Digging deeper, I realized that my upstream configuration in OpenResty was set to use localhost. Here's what I had in:

Now, here's the tricky bit: My server (hosted on Hetzner Cloud) had both IPv4 and IPv6 addresses. So when OpenResty resolved localhost, it could resolve to either 127.0.0.1 (IPv4) or ::1 (IPv6).
In this case, it defaulted to IPv6.
But my .NET app was only listening on 127.0.0.1, not on [::1].
That’s why the requests hung — OpenResty was trying to connect over IPv6 and failing silently until a 90-second timeout occurred.
✅ The Fix
A simple change saved the day.
I edited the upstream configuration and replaced localhost with 127.0.0.1 to force IPv4:
/usr/local/openresty/nginx/common/upstreams.conf (After):

Then, I reloaded OpenResty: systemctl reload openresty.service
And just like that — the UI instantly became responsive.
💡 Takeaway
localhost can resolve to both 127.0.0.1 and ::1.
If your app only binds to IPv4 (127.0.0.1), make sure your reverse proxy uses that explicitly.
Using cloud providers like Hetzner that support IPv6 can expose these subtle issues.
Logs are your best friend when debugging "invisible" issues like long timeouts.
What looked like a huge frontend bug turned out to be a tiny config mistake. A 1-line change that made all the difference.
Thanks for reading! Hope this helps someone avoid hours of head-scratching like I had to.