Connect to PostgreSQL
How to connect to PostgreSQL databases in Python, JavaScript, and Java.
Overview
PostgreSQL is the most popular open-source relational database. Connecting to it reliably requires handling connection strings, SSL, and connection pooling. Below is the idiomatic way to how to connect and query PostgreSQL in Python, JavaScript, and Java.
When to Use
Use this resource when:
- Building web applications that persist data to PostgreSQL
- Migrating from SQLite or MySQL to PostgreSQL
- Setting up data pipelines that read from or write to PostgreSQL
Solution
Python
import psycopg2
from psycopg2.extras import RealDictCursor
# Basic connection
conn = psycopg2.connect(
host="localhost",
database="mydb",
user="user",
password="pass",
sslmode="require"
)
cursor = conn.cursor(cursor_factory=RealDictCursor)
cursor.execute("SELECT * FROM users WHERE id = %s", (1,))
row = cursor.fetchone()
cursor.close()
conn.close()
JavaScript
const { Pool } = require('pg');
const pool = new Pool({
host: 'localhost',
database: 'mydb',
user: 'user',
password: 'pass',
ssl: { rejectUnauthorized: false },
max: 20
});
async function getUser(id) {
const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
return result.rows[0];
}
Java
import java.sql.*;
public class PostgresConnect {
public Connection connect() throws SQLException {
String url = "jdbc:postgresql://localhost:5432/mydb?sslmode=require";
return DriverManager.getConnection(url, "user", "pass");
}
public void queryUser(int id) throws SQLException {
try (Connection conn = connect();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?")) {
stmt.setInt(1, id);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("email"));
}
}
}
}
Explanation
All three examples use prepared statements (parameterized queries) to prevent SQL injection. The Python example uses psycopg2, the standard PostgreSQL adapter. The JavaScript example uses pg with a connection pool, which reuses connections across requests. The Java example uses JDBC, the standard Java database API, with try-with-resources to ensure connections close automatically.
Variants
| Technology | Approach | Notes |
|---|---|---|
| Python | asyncpg | Async PostgreSQL driver for asyncio |
| JavaScript | pg-promise | Helper library with transactions and tasks |
| Java | HikariCP | High-performance JDBC connection pool |
What Works
- Always use connection pools in production rather than creating connections per request
- Store credentials in environment variables or secret managers, never in code
- Use SSL (
sslmode=require) for all production connections - Prefer prepared statements over string concatenation for live values
- Close cursors and connections explicitly or use context managers
Common Mistakes
- Hardcoding database credentials in source code
- Creating a new connection for every query instead of using a pool
- Forgetting to close connections, causing “too many connections” errors
- Disabling SSL verification in production (
sslmode=disable) - Using Python f-strings or JS template literals for SQL queries
Additional Variants
| Technology | Driver | Async | Pooling | Notes |
|---|---|---|---|---|
| Python | psycopg2 | No | Manual or SimpleConnectionPool | Mature, stable |
| Python | psycopg3 | Yes | Built-in | Recommended for new projects |
| Python | asyncpg | Yes | Built-in | Fastest async driver |
| JavaScript | pg | Yes (Promise) | Pool built-in | Standard Node.js driver |
| JavaScript | pg-promise | Yes | Built-in | Extra helpers for tasks |
| Java | JDBC | No | HikariCP | Industry standard |
| Go | pgx | Yes | pgxpool | High performance |
Frequently Asked Questions
What is the difference between psycopg2 and psycopg3?
psycopg2 is the mature, stable driver. psycopg3 (now just psycopg) adds async support, better type handling, and is the recommended choice for new projects.
How many connections should my pool have?
A good starting point is (2 x CPU cores) + effective_spindle_count for the database, divided by the number of app instances. Monitor pg_stat_activity and adjust.
Should I use sslmode=require or verify-full?
Use verify-full when you have the CA certificate and want to verify the server identity. Use require when you need encryption but do not have or trust the CA chain.
Python with context manager and connection pool
import psycopg2
from psycopg2 import pool
from contextlib import contextmanager
# Create a connection pool
pg_pool = pool.SimpleConnectionPool(
minconn=1,
maxconn=10,
host="localhost",
database="mydb",
user="user",
password="pass",
sslmode="require"
)
@contextmanager
def get_db_cursor():
conn = pg_pool.getconn()
try:
cursor = conn.cursor()
yield cursor
conn.commit()
cursor.close()
except Exception:
conn.rollback()
raise
finally:
pg_pool.putconn(conn)
# Usage
with get_db_cursor() as cur:
cur.execute("SELECT * FROM users WHERE active = %s", (True,))
rows = cur.fetchall()
for row in rows:
print(row)
Python async with asyncpg
import asyncio
import asyncpg
async def main():
conn = await asyncpg.connect(
host="localhost",
database="mydb",
user="user",
password="pass",
ssl="require"
)
# Parameterized query
row = await conn.fetchrow(
"SELECT * FROM users WHERE id = $1", 1
)
print(row)
# Batch insert
await conn.executemany(
"INSERT INTO logs (level, message) VALUES ($1, $2)",
[("INFO", "startup"), ("WARN", "high latency")]
)
await conn.close()
asyncio.run(main())
JavaScript with transaction handling
const { Pool } = require('pg');
const pool = new Pool({
host: 'localhost',
database: 'mydb',
user: 'user',
password: 'pass',
ssl: { rejectUnauthorized: false },
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000
});
async function transferBalance(fromId, toId, amount) {
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query(
'UPDATE accounts SET balance = balance - $1 WHERE id = $2',
[amount, fromId]
);
await client.query(
'UPDATE accounts SET balance = balance + $1 WHERE id = $2',
[amount, toId]
);
await client.query('COMMIT');
} catch (err) {
await client.query('ROLLBACK');
throw err;
} finally {
client.release();
}
}
Java with HikariCP connection pool
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.*;
public class PostgresPool {
private static final HikariDataSource ds;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setUsername("user");
config.setPassword("pass");
config.addDataSourceProperty("sslmode", "require");
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setIdleTimeout(30000);
config.setConnectionTimeout(5000);
ds = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static void batchInsert(List<String> emails) throws SQLException {
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO users (email) VALUES (?)")) {
for (String email : emails) {
stmt.setString(1, email);
stmt.addBatch();
}
stmt.executeBatch();
}
}
}
Related Resources
Abstract Factory Pattern
Create families of related objects without specifying concrete classes. A creational design pattern for consistent object families.
PatternAdapter Pattern
Convert the interface of a class into another interface clients expect. A structural design pattern for interface compatibility.
PatternAmbassador: Offload Cross-Cutting Concerns to a Proxy
How to offload cross-cutting concerns to a proxy ambassador. Covers connection pooling, retry logic, circuit breaking, monitoring, and TLS termination for client services.
PatternBridge Pattern: Decouple Abstraction from Implementation
Split a class into two hierarchies — abstraction and implementation — so both can evolve independently. Includes Python, Java, and JavaScript examples.
PatternBuilder Pattern
Construct complex objects step by step. A creational design pattern for readable, configurable object construction.
RecipeConnect to MySQL
How to connect to MySQL databases in Python, JavaScript, and Java.