Homebrew’s PostgreSQL formula is surprisingly opinionated about how your data should be stored, and it’s not immediately obvious why.
Let’s get PostgreSQL up and running. First, make sure you have Homebrew installed. If not, grab it from brew.sh.
Once Homebrew is ready, installing PostgreSQL is a single command:
brew install postgresql
This will download and compile the latest stable version of PostgreSQL and its dependencies. After the installation completes, Homebrew will usually give you a hint about how to start the database:
==> postgresql: To install and run postgresql:
brew services start postgresql
==> postgresql: To connect to your database:
psql postgres
The brew services start postgresql command is the key here. It doesn’t just start the PostgreSQL server process; it also sets it up to launch automatically when your Mac boots. This is managed by launchd, macOS’s system for managing daemons and agents.
Let’s see it in action. After running brew services start postgresql, you can verify it’s running with:
brew services list
You should see postgresql listed with started.
Now, to interact with your new database, use the psql command-line client:
psql postgres
This connects you to the default postgres database with the default postgres user. You’ll see a prompt like postgres=#. You can type \q to exit.
The real magic, and where the opinionated part comes in, is in how Homebrew manages the data directory. By default, Homebrew installs PostgreSQL with its data directory located at:
/usr/local/var/postgres
This is a crucial detail. If you ever need to manually back up your data, move it, or troubleshoot issues related to the data directory, you’ll want to know this path. Homebrew creates this directory, initializes the database cluster within it, and sets up the necessary permissions.
When you run brew services start postgresql, launchd starts the postgres process, which then looks for its configuration files and data in this default location. If you were to manually start postgres without brew services, you’d typically need to specify the data directory using the -D flag, like postgres -D /usr/local/var/postgres.
What if you want to use a different data directory? Homebrew’s formula doesn’t easily expose a way to configure this after installation via a simple brew edit or brew config. You’d generally have to uninstall and reinstall, or manually manage the launchd plist file to point to a new location. The default is chosen for simplicity and to avoid common permission issues that arise when users try to manage data directories in user-owned locations without proper setup.
Consider the postgresql.conf file, which controls most of PostgreSQL’s server settings. It resides within the data directory: /usr/local/var/postgres/postgresql.conf. You can edit this file directly to tune performance, change listening addresses, or adjust logging. After editing, you’ll need to restart the PostgreSQL service for the changes to take effect:
brew services restart postgresql
The pg_hba.conf file, located in the same directory, controls client authentication. This is where you define which users can connect from which hosts and how they authenticate. For example, to allow local connections from any user without a password (for development convenience, not production), you might add a line like:
host all all 127.0.0.1/32 trust
Again, a restart is required after modifying pg_hba.conf.
The Homebrew formula also installs pg_ctl, the PostgreSQL command-line utility for managing the server. You can use pg_ctl directly, but brew services abstracts this away for convenience. For instance, brew services stop postgresql is equivalent to running pg_ctl -D /usr/local/var/postgres stop.
The primary reason Homebrew dictates the data directory location is to standardize the installation and ensure it works seamlessly with launchd without requiring complex user-specific configurations or root privileges for basic operation. It aims for a "just works" experience for most common use cases on macOS.
The next hurdle you’ll often face is managing multiple PostgreSQL versions or instances, which requires moving beyond the default brew services setup.