Install PostgreSQL on Mac with Homebrew: Complete Guide
Chat2DB TeamHomebrew is the standard way to run PostgreSQL on a Mac for development. The install itself is one command, but the details around it — versioned formulae, how the service starts, why there is no postgres user, and what happens to your data when you upgrade — are where people lose time. This guide covers the whole lifecycle: install, first connection, daily service management, major-version upgrades, and the errors specific to Homebrew installs.
Install a versioned formula, not postgresql
Homebrew ships PostgreSQL as versioned formulae: postgresql@18, postgresql@17, and so on. Always install a pinned version:
brew install postgresql@18Why versioned? Because the unversioned name follows whatever Homebrew considers current, and a routine brew upgrade can then jump you across a major version — which PostgreSQL data directories do not survive without a migration step. Pinning to postgresql@18 means upgrades stay within 18.x minor releases, which are always safe.
Check what got installed:
psql --version
# psql (PostgreSQL) 18.4 (Homebrew)If psql is not found, the versioned formula is keg-only and needs a PATH entry:
# Apple Silicon
echo 'export PATH="/opt/homebrew/opt/postgresql@18/bin:$PATH"' >> ~/.zshrc
# Intel Macs use /usr/local instead of /opt/homebrew
source ~/.zshrcStart the server
Two ways to run it:
# As a background service that survives reboots (uses launchd)
brew services start postgresql@18
# Or in the foreground for a one-off session (Ctrl+C stops it)
/opt/homebrew/opt/postgresql@18/bin/postgres -D /opt/homebrew/var/postgresql@18Confirm it is running:
brew services list
# postgresql@18 started ji ~/Library/LaunchAgents/homebrew.mxcl.postgresql@18.plistUseful locations on Apple Silicon:
- Data directory:
/opt/homebrew/var/postgresql@18 - Config:
/opt/homebrew/var/postgresql@18/postgresql.conf - Log file:
/opt/homebrew/var/log/postgresql@18.log
When something fails to start, the log file has the answer — always read it before reinstalling anything.
First connection: there is no postgres user
Unlike Linux packages, Homebrew initializes the cluster with a superuser named after your macOS account, and local connections are trusted (no password). The default database is postgres:
psql postgresThe classic first error here is:
psql: error: connection to server ... FATAL: database "ji" does not existRunning bare psql tries to connect to a database named after your user, which was never created. Either specify the database (psql postgres) or create the personal one so bare psql works forever after:
createdb $(whoami)
psql # now worksSet up a project database and role the way production will look:
CREATE ROLE app LOGIN PASSWORD 'dev-password';
CREATE DATABASE app_dev OWNER app;psql -U app -d app_dev -h localhostNote the -h localhost: password authentication applies to TCP connections; plain psql -U app app_dev uses the local socket, which Homebrew configures as trust.
Daily service management
brew services stop postgresql@18 # stop
brew services restart postgresql@18 # restart after config changes
brew services info postgresql@18 # status detailsReload configuration without a restart from SQL:
SELECT pg_reload_conf();Tail the log while debugging:
tail -f /opt/homebrew/var/log/postgresql@18.logUpgrading
Minor upgrades (18.3 → 18.4) are trivial and data-compatible:
brew upgrade postgresql@18
brew services restart postgresql@18Major upgrades (17 → 18) need a data migration. Homebrew provides a helper that wraps pg_upgrade:
brew install postgresql@18
brew services stop postgresql@17
brew postgresql-upgrade-database # migrates the default data directory
brew services start postgresql@18If the helper is unavailable or fails, the manual route is dump-and-restore:
# With the old server still running
pg_dumpall > ~/pg_backup_all.sql
brew services stop postgresql@17
brew services start postgresql@18
psql -d postgres -f ~/pg_backup_all.sqlEither way, take the dump first. It is the undo button.
Common Homebrew-specific errors
could not connect to server: No such file or directory ... "/tmp/.s.PGSQL.5432" — the server is not running, or crashed on startup. brew services list shows error; read the log. The most frequent root cause after a macOS or Homebrew upgrade is a stale PID file:
rm /opt/homebrew/var/postgresql@18/postmaster.pid
brew services restart postgresql@18Only do this after confirming no postgres process is actually running (pgrep -l postgres).
Server silently fails after a major brew upgrade — the log says The data directory was initialized by PostgreSQL version 17, which is not compatible with this version 18. You upgraded the binaries without migrating data. Run brew postgresql-upgrade-database, or reinstall the old formula (brew install postgresql@17, point it at the data, dump, then migrate properly).
Port 5432 already in use — often Postgres.app or a Docker container is also running. lsof -i :5432 shows the owner. Stop one of them, or run Homebrew's on another port by editing port = 5433 in postgresql.conf.
role "postgres" does not exist — scripts written for Linux assume a postgres superuser. Create it once:
createuser -s postgresInstalling extensions
Homebrew's PostgreSQL includes the contrib extensions (pg_stat_statements, pgcrypto, uuid-ossp, btree_gist and friends) — just enable them per database:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;pg_stat_statements additionally needs a preload entry in /opt/homebrew/var/postgresql@18/postgresql.conf:
shared_preload_libraries = 'pg_stat_statements'followed by brew services restart postgresql@18. Third-party extensions like pgvector have their own formulae that build against your versioned install:
brew install pgvector
psql app_dev -c 'CREATE EXTENSION vector;'If a formula complains about a missing PostgreSQL version, it was built against a different versioned formula than the one you run — brew info pgvector shows which one it links to.
Alternatives worth knowing
- Postgres.app — a menu-bar app bundling several PostgreSQL versions; zero terminal setup, nice for beginners.
- Docker —
docker run -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres:18gives you a disposable server that exactly matches a Linux production image.
Homebrew remains the best default for daily development because psql, libpq and extensions are on your PATH and services persist across reboots. It also plays well with the other two: you can keep Homebrew's psql as your client while the server itself runs in Docker — just mind who owns port 5432.
Add a GUI on top
For browsing schemas, editing rows and writing longer queries, pair the Homebrew server with a desktop client. Chat2DB (opens in a new tab) is a free, native option for macOS (Apple Silicon and Intel): connect with host localhost, port 5432, user = your macOS username, empty password, database postgres — the same defaults Homebrew created. Its AI assistant generates and explains SQL against your real schema, which is genuinely useful when exploring an unfamiliar database; a browser version lives at app.chat2db.ai (opens in a new tab) if you prefer not to install anything.
Summary
brew install postgresql@18
echo 'export PATH="/opt/homebrew/opt/postgresql@18/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
brew services start postgresql@18
createdb $(whoami)
psqlFive commands: install a versioned formula, put it on PATH, start it with brew services, create your personal database, connect. Remember the two Homebrew quirks — the superuser is your macOS username, and major-version upgrades require brew postgresql-upgrade-database — and PostgreSQL on a Mac stays boring in the best possible way.
