Как подключить PostgreSQL к Node.js: пошаговое руководство
Если вы только начинаете работать с Node.js и хотите использовать PostgreSQL как базу данных - эта статья для вас. Разберём всё с нуля: установку, подключение, работу с запросами и типичные ошибки, которые съедают часы времени у новичков.
Что такое pg и зачем он нужен
Для работы с PostgreSQL в Node.js используют библиотеку pg (node-postgres) - самый популярный и зрелый клиент. Она позволяет:
выполнять SQL-запросы из JavaScript/TypeScript;
управлять пулом соединений;
работать с транзакциями и prepared statements.
Есть альтернативы - sequelize, prisma, knex - но это ORM/Query Builder поверх того же pg. Начинать стоит именно с нативного клиента, чтобы понимать, что происходит под капотом.
Почему именно PostgreSQL + Node.js
Связка популярна по нескольким причинам:
PostgreSQL - одна из самых мощных open-source СУБД с поддержкой JSON, полнотекстового поиска и сложных запросов.
Node.js с асинхронной моделью отлично подходит для неблокирующей работы с БД.
Экосистема зрелая: документация, примеры, community - всё есть.
Установка и настройка
1. Установите библиотеку pg
npm install pgДля TypeScript-проектов дополнительно:
npm install --save-dev @types/pg2. Простое подключение через Client
const { Client } = require('pg');
const client = new Client({
host: 'localhost',
port: 5432,
database: 'mydb',
user: 'postgres',
password: 'yourpassword',
});
async function main() {
await client.connect();
const res = await client.query('SELECT NOW()');
console.log(res.rows[0]);
await client.end();
}
main().catch(console.error);Client создаёт одно соединение. Подходит для скриптов, но не для веб-приложений.
3. Подключение через пул (Pool) - правильный подход
Для сервера всегда используйте Pool - он управляет несколькими соединениями автоматически:
const { Pool } = require('pg');
const pool = new Pool({
host: 'localhost',
port: 5432,
database: 'mydb',
user: 'postgres',
password: 'yourpassword',
max: 10, // максимум соединений
idleTimeoutMillis: 30000,
});
async function getUsers() {
const result = await pool.query('SELECT * FROM users LIMIT 10');
return result.rows;
}4. Переменные окружения - обязательно
Никогда не хардкодьте пароли. Используйте .env:
DATABASE_URL=postgresql://postgres:yourpassword@localhost:5432/mydb
require('dotenv').config();
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});Установите dotenv:
npm install dotenvЧастые ошибки и как их исправить
ECONNREFUSED 127.0.0.1:5432
PostgreSQL не запущен или слушает другой порт.
Решение: проверьте статус сервиса:
# Linux / macOS
sudo service postgresql status
# или
pg_isready -h localhost -p 5432password authentication failed for user "postgres"
Неверные учётные данные или pg_hba.conf не настроен.
Решение: проверьте пользователя в psql:
psql -U postgres -c "\du"Или сбросьте пароль:
ALTER USER postgres WITH PASSWORD 'newpassword';Утечка соединений
Если вы используете client.connect() и забываете вызвать client.release() в пуле - соединения накапливаются.
Правильно с пулом:
const client = await pool.connect();
try {
const res = await client.query('SELECT * FROM orders');
return res.rows;
} finally {
client.release(); // обязательно!
}SQL-инъекции через конкатенацию строк
// ОПАСНО - никогда так не делайте
const query = `SELECT * FROM users WHERE id = ${userId}`;Правильно - параметризованные запросы:
const result = await pool.query(
'SELECT * FROM users WHERE id = $1',
[userId]
);Примеры реальных сценариев
Создание таблицы и вставка данных
await pool.query(`
CREATE TABLE IF NOT EXISTS products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price NUMERIC(10,2),
created_at TIMESTAMP DEFAULT NOW()
)
`);
await pool.query(
'INSERT INTO products (name, price) VALUES ($1, $2)',
['Ноутбук', 59999.99]
);Транзакция
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [500, 1]);
await client.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [500, 2]);
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}Часто задаваемые вопросы (FAQ)
Q: Что лучше - pg или prisma?
A: Для старта - pg даёт полный контроль. Prisma удобна в больших проектах с TypeScript, но добавляет абстракцию. Начните с pg, потом решите.
Q: Можно ли использовать pg с TypeScript?
A: Да. Установите @types/pg и типизируйте результаты: pool.query<MyType>(...).
Q: Как подключиться к PostgreSQL на Railway / Supabase / Heroku?
A: Используйте connectionString из переменной окружения. Для SSL-соединений добавьте:
ssl: { rejectUnauthorized: false }Q: Сколько соединений ставить в max?
A: Зависит от сервера. Для старта - 10. Стандартный PostgreSQL держит 100 соединений по умолчанию.
Q: Почему pool.query иногда зависает?
A: Скорее всего, пул исчерпан из-за утечки соединений. Проверьте, что везде вызывается client.release().
Q: Как посмотреть активные соединения в PostgreSQL?
SELECT * FROM pg_stat_activity WHERE datname = 'mydb';Q: Поддерживает ли pg async/await?
A: Да, начиная с версии 7+. Все методы возвращают Promise.
Q: Как правильно закрыть пул при завершении процесса?
process.on('SIGINT', async () => {
await pool.end();
process.exit(0);
});Лучшие практики
Всегда используйте Pool для HTTP-серверов, Client - только для разовых скриптов.
Храните конфиг в .env и добавьте .env в .gitignore.
Используйте параметризованные запросы - это защита от SQL-инъекций.
Логируйте ошибки подключения отдельно от ошибок запросов.
Не создавайте новый Pool при каждом запросе - создайте один инстанс и экспортируйте его.
Следите за idleTimeoutMillis - в production-среде устанавливайте разумные значения (30000–60000 мс).
Для production используйте connection string с SSL и проверяйте сертификаты.
Итог
Подключить PostgreSQL к Node.js несложно, если сделать это правильно с самого начала: Pool вместо Client, переменные окружения вместо хардкода, параметризованные запросы вместо конкатенации строк. Эти три правила закроют 90% проблем, с которыми сталкиваются новички.
Начните с базового примера выше, добавьте .env, настройте пул - и у вас будет стабильная основа для любого Node.js-приложения.
Комментарии
Чтобы оставить комментарий, войдите в аккаунт.