Tips > Ops & Security

Use Docker Compose with Health Checks for n8n and PostgreSQL

The default Docker Compose setup has no health checks, which means Docker will consider a container "running" even if the application inside has crashed

The default Docker Compose setup has no health checks, so Docker treats a container as running even when the app inside has crashed or is stuck in a boot loop. Adding health checks lets Docker detect failures and restart containers automatically, and a depends_on condition makes n8n wait until PostgreSQL is truly ready before it tries to connect.

Why add health checks to n8n's Docker Compose?

The default Docker Compose setup has no health checks, which means Docker will consider a container "running" even if the application inside has crashed or is stuck in a boot loop. Adding health checks enables Docker to detect failures and automatically restart containers, and it ensures n8n waits for PostgreSQL to be truly ready before attempting to connect.

Real-world example: Your PostgreSQL container starts but takes 15 seconds to initialize its data directory on first boot. Without a health check and depends_on condition, n8n starts immediately, fails to connect, and crashes.

How do you add health checks for n8n and PostgreSQL?

version: "3.8"

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  n8n:
    image: n8nio/n8n:1.94.1
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: 5432
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_HOST: ${N8N_HOST}
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://${N8N_HOST}/
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:5678/healthz || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

volumes:
  postgres_data:
  n8n_data:

What does the health-check configuration guarantee?

With this configuration, Docker will not start n8n until PostgreSQL reports healthy via pg_isready, and both containers will be automatically restarted if their health checks fail consecutively.

Related: Set a Unique Encryption Key and Back It Up · Configure Payload Size and Binary Data Mode for Large Files

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

190 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book an introductory call