Good question 👍 — let’s break down upstream_status=500 in Kong.
🔹 What it means
- 500 = Internal Server Error returned by your upstream service, not Kong.
- Kong successfully forwarded the request to the backend, got a real HTTP response, and passed that status back.
- So unlike
502/503/504(which usually mean Kong couldn’t reach the upstream), a 500 means Kong did reach it, but the app/server itself failed internally.
🔹 Common causes
- Unhandled exception in the app (backend crashed while processing request).
- Bad input from client → app logic throws error instead of handling gracefully.
- Dependency failure in upstream (e.g., DB connection error, null pointer, etc.).
- Misrouted traffic (Kong points to wrong host/port → some service returns 500).
- Authentication mismatch (upstream expected something different, failed internally).
🔹 How to verify it’s the upstream
- Check Kong’s access log:
status=500 upstream_status=500→ Both match = the error truly comes from upstream.status=401 upstream_status=200→ Kong overrode the upstream result (plugin decision). - If you’re unsure, temporarily point the route directly to a test echo server (
httpbinormockbin) and re-run → if 500 disappears, your real upstream is the culprit.
🔹 Troubleshooting steps
- Direct test upstream (bypass Kong):
curl -i http://<upstream_host>:<port>/<path>If you still get 500 → it’s an upstream bug. - Enable upstream error logging in Kong (in debug mode or use a logging plugin → Splunk/ELK).
- Check app logs on the backend service for stack traces.
- If you see
status=502 upstream_status=-→ that’s different (connection failed, no response).
✅ So, in short:upstream_status=500 means your app/service returned a 500 → Kong didn’t block it, just proxied it.
Do you want me to also list the difference between 500 vs 502 vs 503 vs 504 in Kong upstream_status, so you can quickly tell where the problem is (Kong vs upstream)?