PostgreSQL Connection Refused — Service Not Started Fix
After PostgreSQL install, psql returns 'connection refused' because the server isn't running — confirm with pg_isready.
20+ years shipping high-throughput database systems. Everything here is grounded in real deployments.
- ✓Basic programming fundamentals
- ✓A computer with internet access
- ✓Willingness to follow along with examples
- PostgreSQL is a relational database server that listens on port 5432 by default
- Install via OS-specific package manager: apt (Linux), Homebrew (macOS), EnterpriseDB installer (Windows)
- Service must be started separately after installation; it's not auto-started on all platforms
- First connection uses the superuser 'postgres'; create a dedicated user for apps
- Use
psqlcommand-line client or GUI tools like pgAdmin to interact - Performance insight: idle memory ~20MB, new connection overhead ~2ms
- Biggest mistake: assuming installation also starts the server — always verify with
pg_isready
PostgreSQL is a relational database management system (RDBMS) that stores and retrieves data using SQL, but unlike MySQL or SQLite, it's built for serious production workloads — think ACID compliance, MVCC for concurrent reads/writes, and support for advanced data types like JSONB, arrays, and custom extensions. It's the database behind companies like Instagram, Reddit, and Apple's iCloud, and it's the default choice for many modern applications because it handles complex queries, large datasets, and concurrent connections without falling over.
You'd use PostgreSQL when you need reliability, data integrity, and features like full-text search, geospatial queries (via PostGIS), or transactional guarantees that simpler databases like SQLite can't provide. Don't use it for ephemeral data, embedded apps, or when you need zero-config — that's what SQLite or a key-value store like Redis is for.
The 'connection refused' error you're hitting almost always means the PostgreSQL service isn't running, which is the first thing you'll fix after installation. On Windows, that's a background service you start via pg_ctl or the Services panel; on macOS, it's brew services start postgresql; on Linux, it's systemctl start postgresql.
Once the service is alive, you connect with psql -U postgres, create a database with CREATE DATABASE myapp;, and then wire it up from your app using a connection string like postgresql://user:password@localhost:5432/myapp. The troubleshooting section will walk you through the exact commands to check if the service is running, inspect logs, and fix the most common pitfalls — like a missing data directory, port conflicts, or a stale lock file.
Think of PostgreSQL as a super-organised filing cabinet for your app's data. Just like a filing cabinet needs to be physically placed in your office before you can use it, PostgreSQL needs to be installed on your computer before your apps can store anything. Once it's installed, you get a 'filing cabinet manager' (called psql) that lets you create drawers (databases), folders (tables), and actually put papers (data) inside. This guide is about getting that cabinet delivered, assembled, and ready to use.
Every app you use — Instagram, your bank's website, your company's HR system — stores data somewhere. That 'somewhere' is almost always a relational database, and PostgreSQL is one of the most trusted ones on the planet. It's free, open-source, battle-hardened by decades of production use, and it powers everything from small side projects to systems at Apple, Reddit, and Spotify. If you're learning backend development or data engineering, understanding how to get PostgreSQL running locally is literally step one.
What PostgreSQL Actually Is (Before You Install Anything)
PostgreSQL (often called 'Postgres') is a relational database management system — or RDBMS. That's a fancy way of saying it's software that stores data in organised tables, like spreadsheets that can talk to each other. It runs as a background service (a server) on your machine, quietly waiting for instructions. You then connect to it using a client — either the built-in command-line tool called psql, a graphical tool like pgAdmin, or your application's code.
Here's the mental model that makes everything click: PostgreSQL is the engine, your database is the garage it runs in, and your tables are the shelves inside that garage. When you install PostgreSQL, you're installing the engine. Everything else — databases, tables, data — you create yourself after installation.
PostgreSQL supports SQL (Structured Query Language), which is the universal language for talking to relational databases. Every command you type — whether to create a table or fetch some records — is written in SQL. The good news is that SQL reads almost like plain English, so it's one of the friendliest languages to learn.
# After installation, run this command in your terminal to confirm PostgreSQL installed correctly. # The '--version' flag asks PostgreSQL to report which version is running. # If you see a version number, the installation worked. If you see 'command not found', it didn't. psql --version # You should also check that the PostgreSQL server process is running. # On Linux and macOS this uses 'pg_isready', a built-in diagnostic tool. # It pings the server and tells you whether it's accepting connections. pg_isready # On Windows, you can check via Services (services.msc) or run: sc query postgresql-x64-16
Installing PostgreSQL on Windows, macOS, and Linux
Installation differs by operating system, but the end result is the same: a running PostgreSQL server on port 5432 (the default), a superuser account called 'postgres', and the psql command-line tool available in your terminal.
Windows: The easiest path is the EnterpriseDB graphical installer at postgresql.org/download/windows. It walks you through everything with a GUI, installs pgAdmin (a visual database browser), and sets up PostgreSQL as a Windows Service that starts automatically on boot.
macOS: The cleanest method for developers is Homebrew — the macOS package manager. If you don't have Homebrew, install it first from brew.sh. One command then handles the whole PostgreSQL setup. Homebrew also makes upgrades and uninstalls trivial later.
Linux (Ubuntu/Debian): Use apt, the built-in package manager. The PostgreSQL project maintains its own apt repository so you always get the latest stable version rather than an older distribution-packaged one.
Regardless of your OS, after installation you'll need to do two things: start the server, and switch to (or authenticate as) the default 'postgres' superuser account to run your first commands.
# ───────────────────────────────────────────── # WINDOWS (run in PowerShell as Administrator) # ───────────────────────────────────────────── # Download the installer from https://www.postgresql.org/download/windows/ # Then run it and follow the GUI steps. After installation, verify with: psql --version # ───────────────────────────────────────────── # macOS (using Homebrew) # ───────────────────────────────────────────── # Step 1: Install Homebrew if you don't have it yet /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Step 2: Install PostgreSQL (version 16 is current stable) # 'brew install' downloads and installs the package automatically brew install postgresql@16 # Step 3: Add PostgreSQL to your PATH so terminal can find the psql command # Replace '~/.zshrc' with '~/.bash_profile' if you use bash instead of zsh echo 'export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"' >> ~/.zshrc source ~/.zshrc # Step 4: Start the PostgreSQL server. # 'brew services start' registers it so it also auto-starts on every reboot brew services start postgresql@16 # ───────────────────────────────────────────── # Linux — Ubuntu / Debian # ───────────────────────────────────────────── # Step 1: Add the official PostgreSQL apt repository # This ensures we get v16, not an outdated Ubuntu-packaged version sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' # Step 2: Import the repository signing key so apt trusts it wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - # Step 3: Refresh the package list and install PostgreSQL sudo apt-get update sudo apt-get install -y postgresql-16 # Step 4: Start the service and enable it to start on system boot sudo systemctl start postgresql sudo systemctl enable postgresql # Step 5: Confirm the service is running sudo systemctl status postgresql
brew services start is the #1 macOS misstep.First Login, Creating a Database, and Running Your First SQL
Once PostgreSQL is installed and running, you need to connect to it. By default, PostgreSQL creates a system user and a database superuser both named 'postgres'. Think of 'postgres' as the master key that unlocks everything — use it to set things up, but don't use it for your actual app later (more on that in the Gotchas section).
On Linux, you connect by switching to the 'postgres' system user first, then launching psql. On macOS (Homebrew install), your own system user is set up as a superuser automatically, so you can just run psql directly. On Windows, psql is available in the Start Menu under PostgreSQL.
Once inside psql, you'll see the prompt 'postgres=#'. This is your SQL command center. Everything you type here gets executed against the database. SQL commands end with a semicolon — forget the semicolon and psql just waits for more input, which trips up almost every beginner at least once.
The workflow for a brand-new project is always the same: create a database, connect to it, create a table, and insert some rows. Let's do exactly that.
-- ───────────────────────────────────────────── -- STEP 1: Connect to PostgreSQL -- ───────────────────────────────────────────── -- On Linux, first switch to the postgres system user in your terminal: -- $ sudo -i -u postgres -- $ psql -- On macOS (Homebrew) or Windows, just open a terminal and run: -- $ psql -U postgres -- You should now see the psql prompt: postgres=# -- ───────────────────────────────────────────── -- STEP 2: Create a new database for a bookshop app -- ───────────────────────────────────────────── -- CREATE DATABASE makes a fresh, empty database. -- Think of this as buying a brand-new filing cabinet. CREATE DATABASE bookshop_db; -- Verify it was created. '\l' is a psql shortcut that lists all databases. \l -- ───────────────────────────────────────────── -- STEP 3: Connect to the new database -- ───────────────────────────────────────────── -- '\c' stands for 'connect'. Without this, your commands run against -- the default 'postgres' database, not your new bookshop_db. \c bookshop_db -- The prompt changes to: bookshop_db=# -- That '#' confirms you're now inside bookshop_db. -- ───────────────────────────────────────────── -- STEP 4: Create a table to store book records -- ───────────────────────────────────────────── -- A table is like a spreadsheet with defined column types. -- SERIAL = auto-incrementing integer (PostgreSQL assigns the ID automatically) -- VARCHAR(255) = text up to 255 characters -- NUMERIC(10,2) = a number with up to 2 decimal places (perfect for prices) -- NOT NULL = this column can never be left empty CREATE TABLE books ( book_id SERIAL PRIMARY KEY, -- Unique ID auto-assigned to every book title VARCHAR(255) NOT NULL, -- The book's title, required author_name VARCHAR(150) NOT NULL, -- Author's full name, required price NUMERIC(10, 2) NOT NULL, -- Price in dollars, e.g. 12.99 published_year INT -- Year published, optional ); -- ───────────────────────────────────────────── -- STEP 5: Insert some real book data -- ───────────────────────────────────────────── -- INSERT INTO adds rows to the table. -- We don't supply book_id because SERIAL handles that automatically. INSERT INTO books (title, author_name, price, published_year) VALUES ('The Pragmatic Programmer', 'David Thomas', 39.99, 2019), ('Clean Code', 'Robert Martin', 34.50, 2008), ('Designing Data-Intensive Applications', 'Martin Kleppmann', 49.99, 2017); -- ───────────────────────────────────────────── -- STEP 6: Read the data back -- ───────────────────────────────────────────── -- SELECT * means 'give me every column'. -- FROM books tells PostgreSQL which table to read from. SELECT * FROM books; -- ───────────────────────────────────────────── -- STEP 7: Create a dedicated app user (best practice) -- ───────────────────────────────────────────── -- Never connect your app directly with the 'postgres' superuser. -- Create a limited user that only has access to bookshop_db. CREATE USER bookshop_app WITH PASSWORD 'use_a_strong_password_here'; -- GRANT gives this user permission to read/write in our database GRANT ALL PRIVILEGES ON DATABASE bookshop_db TO bookshop_app; -- Also grant access to the tables inside the database \c bookshop_db GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO bookshop_app; -- Confirm the user was created \du
Connecting to PostgreSQL from a Node.js or Python App
Running SQL in psql is great for learning and administration, but in real projects you'll connect from code — a Node.js backend, a Python data script, a Django web app. PostgreSQL doesn't care what language you use, as long as your code sends standard SQL over the network.
Every language has a 'driver' or 'adapter' — a small library that handles the low-level work of opening a connection, sending your SQL, and getting results back. In Python, the most popular driver is psycopg2. In Node.js, it's the 'pg' package.
The connection always needs five pieces of information: the host (usually 'localhost' for local development), the port (5432 by default), the database name, the username, and the password. These are called connection parameters and you should never hardcode them in your source code — use environment variables instead, which keeps passwords out of version control.
Below is a working example in both Python and Node.js that connects to the bookshop_db we created, queries the books table, and prints the results.
# ───────────────────────────────────────────── # PYTHON EXAMPLE — using psycopg2 # ───────────────────────────────────────────── # First, install the driver: # pip install psycopg2-binary import psycopg2 # The PostgreSQL driver for Python import os # Used to read environment variables safely # Read connection details from environment variables. # Set these in your terminal before running: # export DB_HOST=localhost # export DB_NAME=bookshop_db # export DB_USER=bookshop_app # export DB_PASSWORD=use_a_strong_password_here db_host = os.getenv("DB_HOST", "localhost") # Default to localhost db_name = os.getenv("DB_NAME", "bookshop_db") # Our database name db_user = os.getenv("DB_USER", "bookshop_app") # Limited app user db_password = os.getenv("DB_PASSWORD", "") # Never hardcode this try: # psycopg2.connect opens an actual TCP connection to PostgreSQL. # Until this line runs successfully, no SQL can be sent. connection = psycopg2.connect( host=db_host, dbname=db_name, user=db_user, password=db_password, port=5432 # PostgreSQL's default port ) # A cursor is like a temporary workspace for running one SQL statement. # You can have multiple cursors open on the same connection. cursor = connection.cursor() # Execute a SQL query — this does NOT return results yet, just runs the query cursor.execute("SELECT book_id, title, author_name, price FROM books ORDER BY price DESC;") # fetchall() retrieves every result row as a list of tuples all_books = cursor.fetchall() print(f"Found {len(all_books)} books in the database:\n") # Loop through the results and print each book for book_id, title, author_name, price in all_books: print(f" [{book_id}] {title} by {author_name} — ${price}") except psycopg2.OperationalError as connection_error: # This error fires when PostgreSQL isn't running, credentials are wrong, # or the database name doesn't exist. The error message tells you which. print(f"Could not connect to the database: {connection_error}") finally: # Always close the cursor and connection when you're done. # Leaving connections open wastes server resources. if 'cursor' in locals(): cursor.close() if 'connection' in locals(): connection.close() print("\nDatabase connection closed cleanly.") # ───────────────────────────────────────────── # NODE.JS EXAMPLE — using the 'pg' package # Save as connect_to_bookshop_db.js and run with: node connect_to_bookshop_db.js # First install: npm install pg # ───────────────────────────────────────────── /* const { Pool } = require('pg'); // 'Pool' manages a reusable set of connections // Pool reads from environment variables automatically if you name them correctly. // Set: DB_HOST, DB_NAME, DB_USER, DB_PASSWORD, DB_PORT in your environment. const databasePool = new Pool({ host: process.env.DB_HOST || 'localhost', database: process.env.DB_NAME || 'bookshop_db', user: process.env.DB_USER || 'bookshop_app', password: process.env.DB_PASSWORD || '', port: parseInt(process.env.DB_PORT) || 5432, }); async function fetchAllBooks() { let client; try { // 'connect' borrows a connection from the pool client = await databasePool.connect(); const queryResult = await client.query( 'SELECT book_id, title, author_name, price FROM books ORDER BY price DESC' ); console.log(`Found ${queryResult.rowCount} books:\n`); // queryResult.rows is an array of plain JavaScript objects queryResult.rows.forEach(book => { console.log(` [${book.book_id}] ${book.title} by ${book.author_name} — $${book.price}`); }); } catch (queryError) { console.error('Database query failed:', queryError.message); } finally { // Return the connection back to the pool (don't destroy it) if (client) client.release(); await databasePool.end(); } } fetchAllBooks(); */
Troubleshooting Common Installation and Connection Issues
Even after following the installation steps, things can go wrong. Here are the most common problems and how to fix them.
Port 5432 already in use – Another PostgreSQL instance or a different service may already occupy port 5432. Check with sudo lsof -i :5432 (Linux/macOS) or netstat -ano | findstr :5432 (Windows). You can either stop the conflicting service or change the PostgreSQL port in postgresql.conf.
Service fails to start – Check the log file. On Linux it's at /var/log/postgresql/postgresql-16-main.log. Common causes: data directory permissions, insufficient disk space, or a corrupted installation. For Homebrew, use brew services restart postgresql@16 and check the log with tail -f /opt/homebrew/var/log/postgresql@16.log.
pg_hba.conf blocks connections – By default PostgreSQL may only allow local socket connections for the postgres user. To allow password logins from localhost, ensure the file contains a line like host all all 127.0.0.1/32 scram-sha-256.
'psql: command not found' – The PostgreSQL client is not in your PATH. On Linux, reinstall the client package postgresql-client. On macOS, ensure Homebrew's bin directory is in PATH. On Windows, close and reopen your terminal after installation.
'FATAL: database does not exist' – You're trying to connect to a database that hasn't been created. Use createdb yourdbname or CREATE DATABASE yourdbname; inside psql.
'FATAL: role does not exist' – The username you're using isn't a database role. Create it with CREATE USER youruser WITH PASSWORD 'pass'; or check the spelling.
# ───────────────────────────────────────────── # Check what's using port 5432 # ───────────────────────────────────────────── # Linux/macOS: sudo lsof -i :5432 # Windows (PowerShell): netstat -ano | findstr :5432 # ───────────────────────────────────────────── # View PostgreSQL logs # ───────────────────────────────────────────── # Linux (Ubuntu/Debian): sudo tail -f /var/log/postgresql/postgresql-16-main.log # macOS Homebrew: tail -f /opt/homebrew/var/log/postgresql@16.log # Windows (default path for 16): # Check C:\Program Files\PostgreSQL\16\data\pg_log\ # ───────────────────────────────────────────── # Verify and reset password # ───────────────────────────────────────────── sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'new_password';" # ───────────────────────────────────────────── # Reload configuration after editing pg_hba.conf # ───────────────────────────────────────────── sudo systemctl reload postgresql # Linux brew services restart postgresql@16 # macOS # Windows: restart the service from services.msc
tail -20 before diving into random config changes.Why Your Package Manager Matters More Than the Installer
You don't install PostgreSQL. You install a package that brings along the entire service stack—or you install the server in isolation. Most juniors treat apt install postgresql like magic. It's not.
On Linux, the package manager sets up systemd service units, creates the postgres OS user, initializes the data directory under /var/lib/postgresql/<version>/main, and sets default permissions on pg_hba.conf. On Windows, the EnterpriseDB installer does the same but hides the plumbing behind a GUI.
Here's the production insight: you will eventually need to install PostgreSQL on a system with no internet. That means offline package managers or building from source. Understanding what the package manager does means you can replicate it manually when the network is down.
If you're using Docker in staging, you're still using a package manager inside the container image. Know your flavor: apt, yum, dnf, zypper, or choco on Windows. The command changes, the pattern doesn't.
#!/bin/bash # io.thecodeforge # Production-safe PostgreSQL install check echo "Checking if PostgreSQL is already installed..." if command -v pg_isready &> /dev/null; then echo "PostgreSQL found. Skipping install." exit 0 fi DISTRO=$(cat /etc/os-release | grep -oP '(?<=^ID=).*' | tr -d '"') case "$DISTRO" in ubuntu|debian) sudo apt-get update && sudo apt-get install -y postgresql ;; rhel|centos|fedora|rocky) sudo dnf install -y postgresql-server ;; *) echo "Unsupported distro: $DISTRO" exit 1 ;; esac echo "PostgreSQL installed successfully."
apt upgrade will update PostgreSQL to a new minor version. This can restart the service. In production, pin your PostgreSQL version in your package manager config, or use the official PostgreSQL APT repository to control upgrades.The PostgreSQL User Account: Not a Bug, It's a Feature
After installation, you'll see a postgres system user in /etc/passwd. That's deliberate. PostgreSQL's default configuration binds the database superuser to the OS-level postgres account.
This means you cannot just psql -U postgres without first being the postgres OS user. It's a permissions fortress, not an inconvenience. The reason: if an attacker compromises your web application, they don't automatically get database superuser access. They'd need to escalate to the OS user first.
In production, you will create a dedicated database user for each service, using a schema-level grants model. Never use the postgres superuser from application code. The day you do is the day a SQL injection turns into a full data exfiltration.
Here's the pattern: switch to the postgres OS user, create a role with limited privileges, then connect from your app using that role. Lock down pg_hba.conf to require password authentication for remote connections. Local socket trust is fine for admin tasks; it's a disaster for app connections.
-- io.thecodeforge -- Production user creation for a Node.js backend service -- Run as postgres OS user: sudo -u postgres psql -f create_app_user.sql CREATE ROLE app_service WITH LOGIN PASSWORD '${APP_DB_PASSWORD}' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT; -- Grant access to specific database only GRANT CONNECT ON DATABASE myapp_db TO app_service; -- Grant schema-level permissions GRANT USAGE, CREATE ON SCHEMA public TO app_service; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_service; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_service;
First-time user can't connect after installing PostgreSQL
psql -U postgres returns: could not connect to server: Connection refused. Is the server running on host localhost and accepting TCP/IP connections on port 5432?systemctl start postgresql (Linux) or brew services start postgresql@16 (macOS). On Windows, the installer does register the service but it may not be running if the user declined the 'Start the database cluster' option.sudo systemctl start postgresql && sudo systemctl enable postgresql
- macOS: brew services start postgresql@16
- Windows: Open Services (services.msc), find 'postgresql-x64-16', click Start. Then retry psql -U postgres.- Always verify the server process is running before trying to connect.
- Use
pg_isready(built-in) orsystemctl status postgresqlto confirm. - Service management is a separate step from installation.
systemctl status postgresql. On macOS run brew services list | grep postgresql. On Windows check services.msc. If stopped, start it.sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'newpass';". Also check pg_hba.conf method – it must be 'md5' or 'scram-sha-256' for password auth.psql -h localhost -U postgres. If that works, set the PGHOST environment variable.\l inside psql or run createdb bookshop_db. Double-check the exact name.Linux: systemctl status postgresql || macOS: brew services list | grep postgresql || Windows: sc query postgresql-x64-16pg_isreadysudo -u postgres psql -c "ALTER USER postgres PASSWORD 'new_strong_password';"psql -U postgres -h localhost -W| Aspect | psql (Command Line) | pgAdmin (GUI Tool) |
|---|---|---|
| Best for | Scripting, automation, server environments | Visual exploration, beginners learning table structure |
| Comes with PostgreSQL | Yes, always included | Yes, via EnterpriseDB installer (or install separately) |
| Speed for bulk operations | Very fast — no rendering overhead | Slower for large result sets due to UI rendering |
| Learning curve | Steeper — must know psql backslash commands | Gentler — click-through interface |
| Use in production | Yes — standard for DBAs and DevOps | Rarely — GUI tools aren't used on headless servers |
| Running SQL scripts | \i filename.sql — one command | Open file via Query Tool, then execute |
| Seeing table structure | \d tablename | Click the table in the left-side object tree |
| File | Command / Code | Purpose |
|---|---|---|
| check_postgres_version.sh | psql --version | What PostgreSQL Actually Is (Before You Install Anything) |
| install_postgres_all_platforms.sh | psql --version | Installing PostgreSQL on Windows, macOS, and Linux |
| first_database_setup.sql | CREATE DATABASE bookshop_db; | First Login, Creating a Database, and Running Your First SQL |
| connect_to_bookshop_db.py | db_host = os.getenv("DB_HOST", "localhost") # Default to localhost | Connecting to PostgreSQL from a Node.js or Python App |
| troubleshoot_common.sh | sudo lsof -i :5432 | Troubleshooting Common Installation and Connection Issues |
| install-pg.sh | echo "Checking if PostgreSQL is already installed..." | Why Your Package Manager Matters More Than the Installer |
| create_app_user.sql | CREATE ROLE app_service WITH | The PostgreSQL User Account |
Key takeaways
Common mistakes to avoid
4 patternsUsing the 'postgres' superuser for your application
Forgetting the semicolon in psql
PostgreSQL server not running when you try to connect
Hardcoding database credentials in source code
Interview Questions on This Topic
What is the difference between the 'postgres' superuser and a regular PostgreSQL role, and why would you create a separate user for your application instead of using postgres?
Walk me through what happens step-by-step when your Node.js app calls pool.connect() to connect to a PostgreSQL database — what is a connection pool and why does it matter for performance?
pool.connect() is called, the pool first checks if there's an idle connection available. If yes, it returns that connection. If not and the pool hasn't reached max size, it creates a new TCP connection to PostgreSQL, handshakes with startup packet, authenticates (password or cert), and then binds a session. The pool then gives this connection to the caller. After the client calls release(), the connection goes back to the idle pool instead of closing. Connection pooling reduces the overhead of establishing a new TCP connection (typically 1-3ms handshake + authentication) per request. Without pooling, each API request would pay that cost, causing higher latency and more load on the server.If your application throws 'FATAL: password authentication failed for user bookshop_app', what are the three most likely causes and how would you debug each one?
ALTER USER bookshop_app PASSWORD '...'. 2) pg_hba.conf method is 'trust' or 'peer' but you're connecting with password: The configuration file (usually /etc/postgresql/16/main/pg_hba.conf) must have a line like host all bookshop_app 127.0.0.1/32 scram-sha-256. Change the method and reload the config. 3) User does not exist: confirm with \du inside psql as superuser. Create the role if missing. Debug by enabling log_connections in postgresql.conf and checking the log for the exact reason.Frequently Asked Questions
PostgreSQL listens on port 5432 by default. You can change this by editing the 'port' setting in the postgresql.conf file (usually found at /etc/postgresql/16/main/postgresql.conf on Linux), then restarting the service. Changing the port is useful if you're running multiple PostgreSQL instances on the same machine.
A database is the top-level container — you connect to a specific database. A schema is a namespace inside a database that groups tables together. By default, PostgreSQL puts everything in a schema called 'public'. Think of a database as a filing cabinet and a schema as a labelled drawer inside it. Most small projects only ever need the default public schema.
You don't need a local PostgreSQL server to connect to a cloud database — the server lives in the cloud. However, you do need the psql client tools installed locally if you want to connect from your terminal. On macOS and Linux you can install just the client with 'brew install libpq' or 'sudo apt install postgresql-client' without installing the full server.
- Edit pg_hba.conf to allow local trust connections (change 'md5' to 'trust' for local lines). 2) Reload config:
sudo systemctl reload postgresql. 3) Connect without password:psql -U postgres. 4) RunALTER USER postgres PASSWORD 'newpassword';. 5) Revert pg_hba.conf back to 'md5' and reload. This resets the superuser password without needing the old one.
The output 'INSERT 0 1' means one row was inserted. The 0 is the OID (object identifier) — it's typically 0 for tables without OIDs. The number after the space is the actual row count. So 'INSERT 0 1' is success; 'INSERT 0 0' would mean no rows inserted (e.g., if a BEFORE trigger prevented it).
20+ years shipping high-throughput database systems. Everything here is grounded in real deployments.
That's MySQL & PostgreSQL. Mark it forged?
5 min read · try the examples if you haven't