Senior 5 min · March 05, 2026

PostgreSQL Connection Refused — Service Not Started Fix

After PostgreSQL install, psql returns 'connection refused' because the server isn't running — confirm with pg_isready.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • 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 psql command-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
Plain-English First

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.

check_postgres_version.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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
Output
psql (PostgreSQL) 16.2
/var/run/postgresql:5432 - accepting connections
Quick Clarification:
PostgreSQL and MySQL are both relational databases, but they're separate products made by different organisations. PostgreSQL is known for stricter standards compliance, better support for complex queries, and powerful features like JSON storage and full-text search. MySQL is historically more common in web hosting. For new projects, PostgreSQL is generally the stronger choice.
Production Insight
The server must be running before any connection succeeds.
New developers often skip this and blame the installation.
Rule: always verify with 'pg_isready' after setup.
Key Takeaway
PostgreSQL is the engine; you create databases and tables yourself.
Installation != server running – check service status explicitly.

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.

install_postgres_all_platforms.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# ─────────────────────────────────────────────
# 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


# ─────────────────────────────────────────────
# LinuxUbuntu / 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
Output
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled)
Active: active (running) since Mon 2024-06-10 09:14:32 UTC; 3s ago
psql (PostgreSQL) 16.2
Watch Out — Windows PATH Issue:
On Windows, the installer adds psql to your PATH automatically, but only for new terminal windows opened after installation. If you have a terminal open during install and type 'psql', you'll get 'command not found'. Close the terminal completely and open a fresh one — that almost always fixes it.
Production Insight
Homebrew installs PostgreSQL without starting the service.
Forgetting brew services start is the #1 macOS misstep.
Rule: after any install, always start the service manually.
Key Takeaway
Installation is not activation — you must start the server.
Use platform-specific commands to start and enable autostart.

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.

first_database_setup.sqlSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
-- ─────────────────────────────────────────────
-- 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
Output
CREATE DATABASE
List of databases
Name | Owner | Encoding | Collate | Ctype
---------------+----------+----------+------------+------------
bookshop_db | postgres | UTF8 | en_US.UTF8 | en_US.UTF8
postgres | postgres | UTF8 | en_US.UTF8 | en_US.UTF8
You are now connected to database "bookshop_db" as user "postgres".
CREATE TABLE
INSERT 0 3
book_id | title | author_name | price | published_year
---------+----------------------------------------+-------------------+-------+----------------
1 | The Pragmatic Programmer | David Thomas | 39.99 | 2019
2 | Clean Code | Robert Martin | 34.50 | 2008
3 | Designing Data-Intensive Applications | Martin Kleppmann | 49.99 | 2017
(3 rows)
CREATE ROLE
GRANT
List of roles
Role name | Attributes
---------------+------------------------------------------------------------
bookshop_app |
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
Pro Tip — The Semicolon Rule:
In psql, every SQL statement must end with a semicolon (;). If you press Enter and see ' ->' instead of getting a result, psql is waiting for the semicolon. Just type ';' and press Enter — it will execute what you typed. This is the single most common confusion for beginners in their first psql session.
Production Insight
Missing semicolons are the #1 psql frustration for beginners.
The '->' prompt is not an error – it's waiting for input.
Rule: always end a SQL statement with ; before pressing Enter.
Key Takeaway
Logical flow: connect → create database → connect to it → create table → insert data.
Use a dedicated app user instead of superuser in production.

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.

connect_to_bookshop_db.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# ─────────────────────────────────────────────
# 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();
*/
Output
Found 3 books in the database:
[3] Designing Data-Intensive Applications by Martin Kleppmann — $49.99
[1] The Pragmatic Programmer by David Thomas — $39.99
[2] Clean Code by Robert Martin — $34.50
Database connection closed cleanly.
Security Warning — Never Hardcode Passwords:
Putting your database password directly in your source code (like password='mypassword') means it gets committed to Git and is readable by anyone with access to the repo. Always use environment variables or a .env file — and add .env to your .gitignore immediately. This is one of the top causes of real-world data breaches.
Production Insight
Hardcoded credentials in Git repos cause real breaches.
Use environment variables and never commit .env files.
A single hardcoded password exposed on GitHub is enough to compromise your database.
Key Takeaway
Always use a dedicated app user with minimal permissions.
Store connection parameters in environment variables, not in code.

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.

troubleshoot_common.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# ─────────────────────────────────────────────
# 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
Output
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
postgres 12345 postgres 7u IPv4 0x123456789 0t0 TCP *:5432 (LISTEN)
Pro Tip — The Log Is Your Best Friend:
When PostgreSQL refuses to start or connect, the log file contains the exact reason. On most systems, it's in /var/log/postgresql/. Always check the last few lines with tail -20 before diving into random config changes.
Production Insight
The PostgreSQL log reveals port conflicts, permission errors, and config mistakes.
Don't guess – read the log first.
Even senior DBAs start debugging with 'tail -f' on the log.
Key Takeaway
Four common issues: port conflict, service not running, pg_hba.conf misconfiguration, or wrong credentials.
Log file is your first diagnostic tool.
● Production incidentPOST-MORTEMseverity: high

First-time user can't connect after installing PostgreSQL

Symptom
Running 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?
Assumption
The user assumes that installing PostgreSQL automatically starts the server and makes it available immediately.
Root cause
On most platforms (especially Linux and macOS via Homebrew), the PostgreSQL service does not start automatically after installation. It must be started manually with 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.
Fix
Start the PostgreSQL service: - Linux: 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.
Key lesson
  • Always verify the server process is running before trying to connect.
  • Use pg_isready (built-in) or systemctl status postgresql to confirm.
  • Service management is a separate step from installation.
Production debug guideThe four symptoms that get beginners stuck4 entries
Symptom · 01
psql: error: could not connect to server: Connection refused
Fix
Check if PostgreSQL service is running. On Linux run systemctl status postgresql. On macOS run brew services list | grep postgresql. On Windows check services.msc. If stopped, start it.
Symptom · 02
FATAL: password authentication failed for user "postgres"
Fix
Verify the password you used during installation. Reset it using 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.
Symptom · 03
psql: error: could not connect to server: No such file or directory
Fix
This means psql is trying to connect via a Unix socket but the socket doesn't exist. Force TCP connection with psql -h localhost -U postgres. If that works, set the PGHOST environment variable.
Symptom · 04
FATAL: database "bookshop_db" does not exist
Fix
The database name is misspelled or not created. List databases with \l inside psql or run createdb bookshop_db. Double-check the exact name.
★ Quick Debug Cheat SheetUse these commands when PostgreSQL won't connect after installation
Cannot connect: Connection refused
Immediate action
Check if PostgreSQL is running
Commands
Linux: systemctl status postgresql || macOS: brew services list | grep postgresql || Windows: sc query postgresql-x64-16
pg_isready
Fix now
Start the service – Linux: sudo systemctl start postgresql; macOS: brew services start postgresql@16; Windows: net start postgresql-x64-16
Password authentication failed+
Immediate action
Reset the postgres password using psql as system user
Commands
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'new_strong_password';"
psql -U postgres -h localhost -W
Fix now
If still failing, check pg_hba.conf (usually /etc/postgresql/16/main/pg_hba.conf) – ensure local and host entries use 'md5' or 'scram-sha-256'
Aspectpsql (Command Line)pgAdmin (GUI Tool)
Best forScripting, automation, server environmentsVisual exploration, beginners learning table structure
Comes with PostgreSQLYes, always includedYes, via EnterpriseDB installer (or install separately)
Speed for bulk operationsVery fast — no rendering overheadSlower for large result sets due to UI rendering
Learning curveSteeper — must know psql backslash commandsGentler — click-through interface
Use in productionYes — standard for DBAs and DevOpsRarely — GUI tools aren't used on headless servers
Running SQL scripts\i filename.sql — one commandOpen file via Query Tool, then execute
Seeing table structure\d tablenameClick the table in the left-side object tree

Key takeaways

1
PostgreSQL runs as a background server on port 5432
it must be started before any client (psql, pgAdmin, or your app) can connect to it.
2
Always create a dedicated, limited-privilege database user for your application
never connect with the 'postgres' superuser in production code.
3
In psql, every SQL statement must end with a semicolon. If you see ' ->' PostgreSQL is waiting for it
just type ';' and press Enter.
4
Store database credentials in environment variables, never in source code
hardcoded passwords in Git repos are one of the most common real-world security failures.
5
When troubleshooting, always check the PostgreSQL log file first
it contains the exact reason for connection failures or startup problems.

Common mistakes to avoid

4 patterns
×

Using the 'postgres' superuser for your application

Symptom
App works fine locally, but you accidentally have full database admin rights in production. A SQL injection bug could drop every table.
Fix
Always CREATE USER with a strong password and GRANT only the permissions that specific app needs. The postgres user is for admin tasks only.
×

Forgetting the semicolon in psql

Symptom
You type a SQL command, press Enter, and see ' ->' instead of a result. psql just sits there waiting. Beginners think it froze.
Fix
Type a semicolon ';' followed by Enter. psql will immediately execute everything you typed. Every SQL statement in psql must end with ';'.
×

PostgreSQL server not running when you try to connect

Symptom
You get 'could not connect to server: Connection refused — Is the server running on host localhost and accepting TCP/IP connections on port 5432?'
Fix
Start the service first. On Linux: 'sudo systemctl start postgresql'. On macOS: 'brew services start postgresql@16'. On Windows: open Services (services.msc) and start 'postgresql-x64-16'.
×

Hardcoding database credentials in source code

Symptom
Passwords committed to Git repos, leakable through public repositories or insider access.
Fix
Always use environment variables or a .env file (added to .gitignore). Read them at runtime from the environment.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the difference between the 'postgres' superuser and a regular Po...
Q02SENIOR
Walk me through what happens step-by-step when your Node.js app calls po...
Q03SENIOR
If your application throws 'FATAL: password authentication failed for us...
Q01 of 03JUNIOR

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?

ANSWER
The 'postgres' superuser has unrestricted access to all databases, tables, and cluster-level operations. In production, an application only needs CRUD permissions on specific tables. Creating a dedicated role (e.g., 'app_user') with GRANT SELECT, INSERT, UPDATE, DELETE ON specific tables limits blast radius – a SQL injection cannot drop tables, read other databases, or change schema. Also, the superuser password is often shared across admin contexts; a leak compromises the entire cluster.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is the default port for PostgreSQL and can I change it?
02
What is the difference between a PostgreSQL database and a schema?
03
Do I need to install PostgreSQL locally if I'm using a cloud database like AWS RDS or Supabase?
04
How do I reset the 'postgres' password if I forgot it?
05
Why does my INSERT result show 'INSERT 0 1' instead of the number of rows?
🔥

That's MySQL & PostgreSQL. Mark it forged?

5 min read · try the examples if you haven't

Previous
MySQL Installation and Setup
3 / 13 · MySQL & PostgreSQL
Next
MySQL Stored Functions