Por que JavaScript se dá bem com PostgreSQL?
\n\nSe você programa em JavaScript (especialmente Node.js) e ainda usa MySQL ou, Deus me livre, SQLite em produção, — você está perdendo dinheiro e paciência. PostgreSQL não é apenas "mais um banco de dados". É um canivete suíço para dados que sabe fazer de tudo: desde JOINs complexos até documentos JSON, busca em texto completo e consultas geoespaciais. E a combinação JavaScript + PostgreSQL é o padrão moderno para aplicações web, microsserviços e análise de dados.
\n\nNeste guia, vamos abordar tudo que um desenvolvedor Node.js precisa saber: desde a instalação do driver até transações, migrações e otimização. Sem enrolação — apenas código e prática.
\n\nPasso 1: Instalação e configuração do driver pg
\n\nPara trabalhar com PostgreSQL a partir do JavaScript, usamos o pacote pg — o cliente oficial. A instalação é rápida:
npm install pg\n\nAgora, criamos a conexão. Existem duas abordagens: Client (uma única conexão) e Pool (pool de conexões). Para produção, sempre use Pool — ele gerencia o reuso de conexões e não sobrecarrega o banco sob carga.
\n\nconst { Pool } = require('pg');\n\nconst pool = new Pool({\n user: 'seu_usuario',\n host: 'localhost',\n database: 'seu_banco',\n password: 'sua_senha',\n port: 5432,\n max: 20, // máx. de conexões no pool\n idleTimeoutMillis: 30000,\n connectionTimeoutMillis: 2000,\n});\n\n// Teste de conexão\npool.query('SELECT NOW()')\n .then(res => console.log('✅ Conectado:', res.rows[0].now))\n .catch(err => console.error('❌ Erro:', err));\n\nImportante: Nunca coloque senhas diretamente no código. Use variáveis de ambiente (process.env.DATABASE_URL) ou um gerenciador de segredos.
Passo 2: CRUD — a base de tudo
\n\nQualquer aplicação começa com CRUD (Create, Read, Update, Delete). Vamos detalhar cada operação com JavaScript e PostgreSQL.
\n\nCriação de tabela (DDL)
\n\nconst createTable = async () => {\n const query = `\n CREATE TABLE IF NOT EXISTS users (\n id SERIAL PRIMARY KEY,\n name VARCHAR(100) NOT NULL,\n email VARCHAR(255) UNIQUE NOT NULL,\n age INTEGER CHECK (age > 0),\n created_at TIMESTAMP DEFAULT NOW()\n );\n `;\n await pool.query(query);\n console.log('✅ Tabela users criada');\n};\n\ncreateTable();\n\nINSERT — adicionar dados
\n\nconst addUser = async (name, email, age) => {\n // Usamos consulta parametrizada — proteção contra injeção SQL!\n const query = `\n INSERT INTO users (name, email, age)\n VALUES ($1, $2, $3)\n RETURNING *;\n `;\n const values = [name, email, age];\n const res = await pool.query(query, values);\n console.log('✅ Usuário adicionado:', res.rows[0]);\n return res.rows[0];\n};\n\n// Exemplo de chamada\naddUser('Ana Silva', 'ana@exemplo.com', 28);\n\nSELECT — leitura com filtro
\n\nconst getUsers = async (minAge = 0) => {\n const query = 'SELECT * FROM users WHERE age > $1 ORDER BY created_at DESC';\n const res = await pool.query(query, [minAge]);\n console.log(`📊 Usuários encontrados: ${res.rowCount}`);\n return res.rows;\n};\n\ngetUsers(25).then(users => console.log(users));\n\nUPDATE — atualizar registro
\n\nconst updateUserEmail = async (id, newEmail) => {\n const query = `\n UPDATE users\n SET email = $2, updated_at = NOW()\n WHERE id = $1\n RETURNING *;\n `;\n const res = await pool.query(query, [id, newEmail]);\n if (res.rowCount === 0) {\n console.log('⚠️ Usuário não encontrado');\n return null;\n }\n console.log('✅ Email atualizado:', res.rows[0]);\n return res.rows[0];\n};\n\nDELETE — remoção
\n\nconst deleteUser = async (id) => {\n const query = 'DELETE FROM users WHERE id = $1 RETURNING *';\n