Fix PostgreSQL Server Won't Start on Mac OS X (2026)
PostgreSQL

Fix PostgreSQL Server Won't Start on Mac OS X (2026)

I hit this wall the first time I installed PostgreSQL through Homebrew on a fresh Mac. The package installed without errors, but when I tried to connect with

2026-09-03
8 min read
Fix PostgreSQL Server Won't Start on Mac OS X (2026)

"How can I start PostgreSQL server on Mac OS X" — the exact commands that work#

I hit this wall the first time I installed PostgreSQL through Homebrew on a fresh Mac. The package installed without errors, but when I tried to connect with psql, I got "connection refused." Running pg_ctl start threw back "pg_ctl: no database directory specified and no PGDATA environment variable." The fix is straightforward once you know which init system your installation uses: if you installed with Homebrew, use brew services start postgresql@16. If you used Postgres.app, start it from the Applications folder. If you built from source or used the EnterpriseDB installer, you need pg_ctl with the -D flag pointing at your data directory. I'll walk through every variant so you can pick the one that matches your setup.

What you'll see#

When PostgreSQL isn't running, you'll encounter one of these symptoms depending on what you try:

Trying to connect with psql:

plaintext
psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such file or directory
        Is the server running locally and accepting connections on that socket?

Trying to start manually with pg_ctl:

plaintext
pg_ctl: no database directory specified and no PGDATA environment variable
Try "pg_ctl --help" for more information.

Or, if you try brew services list and see:

plaintext
postgresql@16  none

It happens right after a fresh install, after a macOS upgrade, or after a reboot if the service wasn't configured to launch at startup. The behavior is the same across macOS Ventura, Sonoma, and Sequoia — the underlying issue is always that the PostgreSQL server process isn't running.

Why PostgreSQL doesn't auto-start on macOS#

macOS doesn't know you installed PostgreSQL. Unlike Linux distributions that wire up systemd units during package installation, Homebrew on macOS gives you the binaries and leaves the service management to you. There are three layers at play here, and missing any one of them means PostgreSQL stays dead.

First, PostgreSQL itself needs an initialized data directory. Homebrew runs initdb for you during installation, creating the cluster at /opt/homebrew/var/postgresql@16 on Apple Silicon or /usr/local/var/postgresql@16 on Intel Macs. If you installed through a different method — the EnterpriseDB graphical installer, Postgres.app, or compiling from source — that directory lives somewhere else, and PostgreSQL has no way to guess where.

Second, macOS uses launchd as its service manager. Homebrew integrates with launchd through brew services, which writes a .plist file to ~/Library/LaunchAgents/. That plist tells launchd what binary to run, what arguments to pass, and whether to restart on failure. If you never ran brew services start, that plist either doesn't exist or exists but isn't loaded.

Third, the PGDATA environment variable is not set by default. When you run pg_ctl start without -D, PostgreSQL looks for PGDATA in your shell environment. It's not there unless you added it to your .zshrc or .bash_profile manually. That's why the "no database directory specified" error is so common — it's not a bug, it's PostgreSQL telling you it needs one piece of information you haven't given it.

The fix: start PostgreSQL with the method that matches your install#

The command you run depends entirely on how PostgreSQL got onto your Mac. Here's the decision tree.

If you installed with Homebrew (most common)#

Find your installed version first:

bash
brew list --versions | grep postgresql

You'll see something like postgresql@16 16.4. Then start the service:

bash
brew services start postgresql@16

Expected output:

text
==> Successfully started `postgresql@16` (label: homebrew.mxcl.postgresql@16)

To have it start automatically on every reboot, that single command is enough — brew services writes the launchd plist and loads it immediately. No separate enable step is needed.

If you used Postgres.app#

Postgres.app is a self-contained application bundle. Start it by opening the app from /Applications/Postgres.app. It adds an elephant icon to your menu bar. Click the icon, and you'll see "Start" if the server isn't running. Once started, it also configures your $PATH so psql works from the terminal — but you may need to restart your terminal or source the path changes.

If you installed via the EnterpriseDB installer or compiled from source#

You need to know where your data directory is. Common locations:

  • EnterpriseDB: /Library/PostgreSQL/16/data
  • Source build (default): /usr/local/pgsql/data

Start with:

bash
pg_ctl -D /Library/PostgreSQL/16/data start

If you get a permissions error, the data directory is owned by the postgres user that the installer created. Switch to that user:

bash
sudo -u postgres pg_ctl -D /Library/PostgreSQL/16/data start

If you don't know where your data directory is#

Search for it:

bash
sudo find / -name "pg_hba.conf" 2>/dev/null

The directory containing pg_hba.conf is your data directory. On my Apple Silicon Mac with Homebrew, that returns:

text
/opt/homebrew/var/postgresql@16/pg_hba.conf

So the data directory is /opt/homebrew/var/postgresql@16.

Verify the fix#

Run pg_isready — it's the simplest check and ships with every PostgreSQL installation:

bash
pg_isready

If PostgreSQL is running and accepting connections, you'll see:

text
/opt/homebrew/var/postgresql@16:5432 - accepting connections

If it's not running:

text
/opt/homebrew/var/postgresql@16:5432 - no response

For Homebrew specifically, confirm the service status:

bash
brew services list

Look for your PostgreSQL version in the output:

text
postgresql@16  started         mahdi ~/Library/LaunchAgents/[email protected]

The "started" status means launchd has the process running and will restart it if it crashes. "none" means the service isn't loaded at all. "error" means launchd tried to start it but the process exited — check the logs with brew services info postgresql@16 to see the last exit code and log file path.

Finally, connect with psql to confirm you can actually run queries:

bash
psql -U postgres -c "SELECT version();"

Expected output:

text
                                                          version
---------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 16.4 (Homebrew) on aarch64-apple-darwin23.6.0, compiled by Apple clang version 15.0.0, 64-bit
(1 row)

Two variants that still trip people up#

Variant A — "Is the server running?" after a macOS upgrade#

macOS upgrades sometimes clear LaunchAgents or change permissions on the data directory. After upgrading to a new major macOS version, you might find brew services list shows your PostgreSQL service as "started" but pg_isready says "no response."

The fix: restart the service so launchd re-registers it under the new OS version:

bash
brew services restart postgresql@16

If that still fails, check the log file. Homebrew logs to ~/Library/Logs/Homebrew/[email protected] by default. A common post-upgrade error is a permissions mismatch on the data directory. Fix it by reassigning ownership:

bash
sudo chown -R $(whoami) /opt/homebrew/var/postgresql@16

Variant B — Port conflict with another PostgreSQL instance#

If you have both Postgres.app and Homebrew's PostgreSQL installed, or if you upgraded PostgreSQL versions and the old one is still running, you'll get a port conflict. The error looks like:

plaintext
pg_ctl: could not start server
Examine the log output.

And the log contains:

plaintext
FATAL:  lock file "postmaster.pid" already exists
HINT:  Is another postmaster (PID 1234) running on port 5432?

Find what's already on port 5432:

bash
lsof -i :5432

Kill the conflicting process or stop the other service:

bash
brew services stop postgresql@15   # if you upgraded from 15 to 16

Then start the version you want. If you need both versions running simultaneously, configure one to use a different port — I cover changing the PostgreSQL port in the PostgreSQL SHOW TABLES / DESCRIBE TABLE guide, where I walk through postgresql.conf edits.

Keep PostgreSQL running across reboots#

The brew services start command handles this automatically — it writes a launchd plist that loads at login. But if you ever need to check or manually manage the plist, it lives at:

bash
cat ~/Library/LaunchAgents/[email protected]

The key fields are RunAtLoad (set to true so it starts at boot) and KeepAlive (set to true so launchd restarts it if it crashes). You can disable auto-start without uninstalling:

bash
brew services stop postgresql@16

This unloads the service but leaves the plist in place. To re-enable:

bash
brew services start postgresql@16

If you ever need to completely remove the service definition, brew services cleanup will delete plists for formula versions that are no longer installed.

For manual pg_ctl users, you can write your own launchd plist or add an alias to your shell config. I prefer the alias approach because it's explicit — I know exactly when PostgreSQL starts:

bash
alias pgstart='pg_ctl -D /opt/homebrew/var/postgresql@16 -l ~/pg.log start'
alias pgstop='pg_ctl -D /opt/homebrew/var/postgresql@16 stop'

Add those to ~/.zshrc, then source ~/.zshrc. Now pgstart and pgstop work from any terminal.

FAQ#

How do I start PostgreSQL after installing it with Homebrew?#

Run brew services start postgresql@16 (replace 16 with your installed version — check with brew list --versions | grep postgresql). This uses launchd to start PostgreSQL and keep it running across reboots. Verify with brew services list to confirm the service status shows "started." If you haven't initialized a database cluster yet, Homebrew does that automatically during installation, but if you skipped it or need to reinitialize, run initdb /opt/homebrew/var/postgresql@16 first.

Why does pg_ctl say "no database directory specified"?#

PostgreSQL needs to know where its data directory lives. If you installed via Homebrew, the data directory is typically at /opt/homebrew/var/postgresql@16 on Apple Silicon or /usr/local/var/postgresql@16 on Intel Macs. Set the PGDATA environment variable in your shell config (export PGDATA=/opt/homebrew/var/postgresql@16 in ~/.zshrc) or pass -D /path/to/data explicitly to pg_ctl. If you're unsure where your data directory is, search for pg_hba.conf — the directory containing that file is your data directory.

How do I check which version of PostgreSQL I'm running?#

Run psql --version from the terminal or connect and run SELECT version();. If psql isn't found, you may need to install the client tools first — I cover that exact scenario in Fix: psql: command not found. For a deeper dive into version checking methods, including how to query the server version remotely, see Which version of PostgreSQL am I running?.

Can I have multiple PostgreSQL versions installed on the same Mac?#

Yes. Homebrew supports this with versioned formulae (postgresql@14, postgresql@15, postgresql@16). Each version gets its own data directory and runs on a different port by default — 5432, 5433, 5434, and so on. Start them independently with brew services start postgresql@14 and brew services start postgresql@16. To connect to a specific version, specify the port: psql -p 5433 -U postgres. If you need to change a user's password across versions, I've documented the exact ALTER ROLE syntax in How to Change a PostgreSQL User Password.

Frequently Asked Questions

|

Have more questions? Contact us

Written by

Mahdi Br
Mahdi Br

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote

One email a month — no fluff

RLS gotchas, Next.js cache debugging, and the one Supabase setting that bit me last month.