Skip to content

A target stays unhealthy

2 min read · main part only; folded sections are optional

After this you can answer: Why is an ECS container running while the ALB target is unhealthy?

Diagnostic scenario: EC2 → Target groups shows Request timed out or Health checks failed with these codes: [404]. ECS may show a running container, then replace it after failed health checks.

The ALB checks the target’s private IP and port. A timeout suggests Reach or a slow process. A 404 proves the process replied, so check the path. This is not an IAM Allowed denial or a DB Password failure. Container health is a separate check from target health.

flowchart TB
A[Unhealthy target reason] --> B{HTTP status returned?}
B -->|404 or redirect| C[Check path and matcher]
B -->|5xx| D[Read health-route logs]
B -->|timeout| E{Process listening correctly?}
E -->|no| F[Check bind address and port]
E -->|yes| G[Check SG path and latency]

Rank within the observed branch:

  1. Wrong status: health path changed. API must check /health on 4000; web checks / on 3000; both expect 200.
  2. Timeout after network change: task security group no longer allows ALB’s security group on that port.
  3. Timeout after image change: process binds only to localhost, uses the wrong port, crashes, or takes too long.
  4. Only during startup: startup exceeds the configured grace period. Establish that before extending it.

EC2 → Target groups → Targets → Health status details, then Health checks. ECS → task → Health status, logs and Network. Compare API HOST=0.0.0.0 or web HOSTNAME=0.0.0.0 with task port mappings and SG rules.

Restore the correct path, bind address or SG source. API inbound TCP 4000 and web inbound TCP 3000 allow the ALB group in infra/src/security.ts → createSecurityGroups. Keep ALB health independent of temporary DB failures: use /health, not /ready.

Review target and container checks together. Target checks have a 15-second interval, 5-second timeout and 200 matcher; ECS allows 60 seconds for startup. Test that the production image listens on the container interface before deploying it.

Advanced: Read the two health systems separately

A container health check runs inside the task. The API’s command fetches localhost:4000/health; it cannot prove the ALB can reach the task interface. The ALB probes from outside the task. Both settings live in infra/src/compute/task.ts → createApiTask and infra/src/entry/target-groups.ts → createTargetGroups.

The group requires three failures before an established target becomes unhealthy and two successes to recover. Newly registered targets have different initial-health behavior: AWS needs one successful initial check. Do not estimate exact recovery time by multiplying thresholds alone; startup, registration and probe timing also matter. AWS defines health states and reasons.

If all targets are unhealthy in every enabled Availability Zone, ALB can fail open and route to them. A green container or an occasional 200 therefore does not replace target-health review.

Read this book online: https://book.theversehub.in/