Как подключить PostgreSQL к Node.js: пошаговое руководство

mr. Cooper 11 часов назад Веб-разработка
Как подключить 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/pg

2. Простое подключение через 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 5432

password 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-приложения.

Комментарии

Пока нет комментариев. Будьте первым, кто напишет.

Чтобы оставить комментарий, войдите в аккаунт.

Похожие статьи