Skip to content

The API cannot reach Postgres

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

After this you can answer: How do you distinguish a database network problem from a bad password?

Diagnostic scenario: API logs contain ETIMEDOUT, /ready fails, or logs instead say password authentication failed. Those messages describe different failure stages; no historical outage is claimed here.

DNS or TCP timeout is Reach: can the API find and connect to RDS, AWS’s managed database? A certificate error concerns TLS, which encrypts and verifies the connection. Postgres authentication is Password; database permission denied is a SQL grant issue. MiniTickets uses password login, so IAM Allowed does not grant SQL access.

flowchart TB
A[First database error] --> B{DNS resolves?}
B -->|no| C[Check endpoint and VPC DNS]
B -->|yes| D{TCP connects?}
D -->|no| E[Check DB state, SGs and routes]
D -->|yes| F{TLS succeeds?}
F -->|no| G[Check CA and hostname]
F -->|yes| H[Check password or SQL grants]

Rank within the error branch:

  1. Timeout after network change: DB inbound TCP 5432 no longer names API’s security group, or the task has a different group.
  2. Name/endpoint failure: stale DB_HOST after recreation or VPC DNS changed.
  3. Authentication after rotation: the running task still holds the old injected password.
  4. TLS error: missing RDS certificate authority (CA), wrong hostname or client SSL configuration. Also check RDS availability before blaming the client.

RDS → minitickets-dev-db → status, endpoint, port, VPC and SG. ECS → API task → Network: confirm api-sg. EC2 → db-sg → Inbound: TCP 5432 from api-sg only. Compare API error timestamps with RDS events and secret rotation metadata.

Restore only API-to-DB TCP 5432 in infra/src/security.ts → createSecurityGroups. Refresh tasks after credential rotation. Repair TLS trust through apps/api/src/config/database.ts → DatabaseEnvSchema; keep certificate verification enabled. Do not make RDS public to repair an internal path.

Keep endpoint and SG references wired from resources. Compare /health with /ready: liveness can pass while DB readiness fails. Test production TLS configuration and plan credential refresh for long-running tasks.

Advanced: A private DB does not need a NAT gateway for this path

API and RDS communicate through the VPC’s local route. The database has no public IP and lives in private subnets. It does not need internet access to answer API queries. Security groups allow replies to established traffic, so the DB group’s empty egress list does not block query responses.

The API pool has a 2-second acquisition/connect timeout, a 5-second statement timeout and at most 10 connections in apps/api/src/db/client.ts → pool. A pool-acquisition timeout can also mean all connections are busy; inspect connection and query load before treating every timeout as dropped network packets.

RDS setup is in infra/src/data/postgres.ts → createPostgres; the task reads DB credentials only at startup in infra/src/compute/task.ts → createApiTask. AWS documents startup-injected secrets.

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