App Hangs on Startup: How to Find the Blocking Connection

When an app hangs or dies right after a line like 'Connecting to upstream service...', it is waiting on a network dependency it cannot reach. Most often the config points at the wrong host or port. Compare the configured address with the port the dependency really listens on, then correct the config.

Start this project - freeLive cloud workspace in your browser · lands on your portfolio
DevOps Engineerpythonlinuxnetworking

Why apps get stuck at startup

Many services check their dependencies before they accept traffic: a database, a cache, an internal API. That check is a network connection. If the address is wrong, one of two things happens:

Either way, the last line in the log is the clue.

Step 1: read the last lines of the log

curl -s http://localhost:8080/health      # no answer
tail -n 8 /var/log/app.log

Example output:

Connecting to upstream service at 127.0.0.1:9999...
ERROR: Cannot reach upstream service at 127.0.0.1:9999: [Errno 111] Connection refused
FATAL: upstream unavailable, exiting

The app tells you exactly which host and port it tried. Write them down.

Step 2: find where the dependency really listens

List listening TCP ports and the process behind each one:

ss -ltnp          # or: netstat -tlnp
LISTEN 0  128  0.0.0.0:5000  0.0.0.0:*  users:(("python3",pid=41,fd=3))

Confirm the dependency answers on that port:

curl -s http://localhost:5000/health

If it answers on 5000 but the app dials 9999, the config is wrong, not the dependency.

Step 3: correct the config

; config.ini
[upstream]
host = 127.0.0.1
port = 5000      ; was 9999 - nothing listens there

Restart the app (or let its supervisor restart it) and confirm:

tail -n 3 /var/log/app.log
curl -s http://localhost:8080/health

Change the config, not the dependency. Other services may already use the dependency on its current port.

When the process hangs with no log output

If the app prints nothing and never exits, find out what it is waiting on:

# Which connections does the process have open?
ss -tnp | grep <pid>

# Which system call is it blocked in?
strace -p <pid>

A connection in state SYN-SENT means the app is waiting for a host that does not answer. For Python apps, py-spy dump --pid <pid> (if installed) prints the current stack and shows the exact line that is blocked.

Prevent silent hangs: always set a timeout

The worst startup bug is one with no error and no progress. Always give a network call a timeout:

import socket

def check_upstream(host, port, timeout=5):
    try:
        with socket.create_connection((host, port), timeout=timeout):
            return True
    except OSError as e:
        print(f'ERROR: cannot reach {host}:{port}: {e}')
        return False

Most clients have a timeout option: requests.get(url, timeout=5), psycopg2.connect(..., connect_timeout=5), redis.Redis(socket_connect_timeout=5). Then decide what happens on failure: retry with backoff, exit with a clear error, or start in a degraded mode. Never wait forever.

Checklist

  1. Read the last log line and note the host and port.
  2. Run ss -ltnp to see the real listening ports.
  3. curl the dependency directly.
  4. Correct the host or port in the config.
  5. Add a timeout so the next mistake fails fast.

Do this project yourself. It's ready in a live cloud workspace in your browser - when you finish, it lands on your portfolio.

Start this project - free

What you'll practice

FAQ

Why does my app hang on startup with no error?

It is most likely blocked on a network connection with no timeout - to a database, cache, or API at an address that does not answer. Check open connections with ss -tnp and add a connect timeout so the call fails instead of waiting forever.

How do I see which port a service is listening on in Linux?

Run ss -ltnp (or netstat -tlnp). It lists every listening TCP port with the process name and PID.

What is the difference between connection refused and connection timed out?

Refused means the host answered but nothing listens on that port, so it fails at once. Timed out means no answer came back at all, usually a wrong host or a firewall dropping packets.

Should an app exit if a dependency is down at startup?

It should never hang. Either retry with backoff for a limited time, exit with a clear error so the supervisor restarts it, or start in a degraded mode and report unhealthy.

Keep learning

Make an App Wait for Postgres on StartupDevOps projectSet an HTTP Client Timeout to Stop Cascading FailuresDevOps projectCorrect a Postgres Port MismatchDevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Do this project yourself. It's ready in a live cloud workspace in your browser - when you finish, it lands on your portfolio.

Start this project - free
Start this project - free