Quick summary
Summarize this blog with AI
This guide installs PostgreSQL 16 for local development on an Apple Silicon Mac using Homebrew. The version is deliberate: an unversioned package can follow a different major release. Use the latest available 16.x maintenance release and check Homebrew’s current macOS support requirements. Intel/Rosetta installs, Docker, Postgres.app, and remote servers have different paths and service management; do not mix their instructions.
This is a fresh-install procedure, not an upgrade or repair recipe. If the Mac already contains PostgreSQL data, identify its installation and backup/restore plan before installing or starting another server. The commands below were checked against official documentation; they were not run to install software or alter services while this article was revised.
1. Confirm Homebrew and the existing environment
If Homebrew is missing, follow its official installation instructions and review the installer’s changes. Once it is available, run these read-only checks individually:
uname -m
brew --prefix
brew list --versions
brew services list
lsof -nP -iTCP:5432 -sTCP:LISTEN
A native Apple Silicon shell normally reports arm64 and uses /opt/homebrew. A different prefix is a reason to understand the environment, not a reason to delete or relink it. Check the installed-package and service lists for every PostgreSQL version. A process listening on 5432 may already be the server you need. No lsof output only establishes that it found no visible TCP listener; it does not prove there are no databases, Unix-socket services, or stopped clusters.
Inspect the versioned default data path as well. If it exists, stop this fresh-install procedure and determine what it contains. A stopped cluster is still valuable data. Do not run initdb over it, remove it, recursively change ownership, or point a different major-version server at it.
brew_prefix="$(brew --prefix)"
ls -ld "$brew_prefix/var/postgresql@16"
“No such file or directory” is expected only for a genuinely absent path. Also check for other known installations and data locations you use. The Homebrew formula’s default path is not a comprehensive inventory of the Mac.
2. Install the named major version and start only its new service
After confirming this is a new local installation, inspect the formula, install it, and use the service name that matches the package:
brew info postgresql@16
brew install postgresql@16
brew services start postgresql@16
brew services list
The PostgreSQL 16 formula creates a default cluster under Homebrew’s var/postgresql@16 path. Its versioned binaries are keg-only, so use their explicit location instead of force-linking them over another client. Starting the service runs it now and registers it to start at login for the current user. Do not add sudo to these routine Homebrew commands.
pg16_prefix="$(brew --prefix postgresql@16)"
"$pg16_prefix/bin/psql" --version
"$pg16_prefix/bin/psql" -h localhost -p 5432 -d postgres
The first command identifies the client. The SQL connection identifies the server separately; installing a new client does not upgrade an existing server. On a fresh Homebrew cluster the initial database role is normally the operating-system user that initialized it. An authentication error is not a reason to weaken authentication globally.
SELECT version(), current_database(), current_user;
SHOW data_directory;
SHOW config_file;
SHOW port;
Verify that the server major version, data directory, port, and role describe the new intended instance. These values are environment-dependent. Exit psql with \q. If you connected to a different server, stop issuing commands and correct the connection target.
3. Inspect configuration before considering tuning
Keep the initial settings until a measured workload establishes a problem. There is no universal laptop configuration that makes all queries fast. work_mem can be consumed by multiple operations and sessions, max_connections affects resource use, and effective_cache_size is a planner estimate rather than memory reserved for PostgreSQL. Copying a large-machine tuning block to a laptop can reduce reliability.
Use SHOW config_file to locate this server’s configuration. Do not assume a path from another tutorial or edit it with sudo merely because a previous install used that command. Before any intentional configuration change, preserve a copy, record the old value, and understand whether it needs a reload or restart. The resource configuration reference explains the scope of individual settings.
4. Plan restarts and upgrades as separate operations
A restart disconnects active work; it is not a required “performance improvement” step after a successful fresh install. If you later need to stop this specific development service, brew services stop postgresql@16 stops and unregisters it without deleting its data. Confirm no application depends on it first. Service commands are described in the Homebrew manual.
A major upgrade needs a supported migration method such as pg_upgrade or dump/restore, compatible extensions, a tested backup, and a rollback plan. It is not accomplished by pointing new binaries at the old data directory. Keep the old cluster until the migrated database and application have been verified. Consult PostgreSQL’s upgrading guide for the chosen source and target versions.
Connection troubleshooting
For “connection refused,” check the named service status, listener port, and that service’s startup log. For “role does not exist,” check the intended cluster and user rather than creating arbitrary superusers. For “database does not exist,” use the explicit postgres database in the connection command. For a port collision, identify the owner; do not kill it or erase its data to make this tutorial work.