Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Aplicar critérios práticos para escolher o banco de um projeto Node.js
- Conhecer os drivers e as armadilhas de PostgreSQL, MySQL, MongoDB, Redis e SQLite no Node.js
- Escolher o banco certo para bot, API ou site, com recomendação por cenário
Node.js conversa bem com praticamente qualquer banco de dados. Todo banco popular tem um driver mantido no npm, e todos trabalham com Promises e async/await. Por isso a pergunta "qual o melhor banco para Node.js" tem menos a ver com o Node e mais com o seu projeto: o formato dos dados, as garantias de que você precisa e quantos processos vão acessar o banco.
Este guia compara as cinco opções mais comuns no ecossistema (PostgreSQL, MySQL, MongoDB, Redis e SQLite) pelo ponto de vista de quem escreve JavaScript. Para cada uma, você vê o driver, um exemplo e as armadilhas que aparecem no dia a dia.
Que critérios importam na escolha?#
Cinco critérios resolvem quase todos os casos:
- Formato dos dados. Usuários, pedidos e inventários com relações entre si pedem um banco relacional. Configurações e perfis com campos que variam de item para item combinam com documentos.
- Transações. Se duas gravações precisam acontecer juntas ou não acontecer (debitar um saldo e creditar outro), prefira um banco com transações maduras.
- Padrão de acesso. Leitura por chave exata em milissegundos, como sessão ou cooldown, é trabalho de Redis. Relatórios que cruzam tabelas são trabalho de SQL.
- Quantos processos acessam. Um processo só pode usar um arquivo local (SQLite). Vários processos, várias aplicações ou réplicas pedem um servidor de banco acessado pela rede.
- Qualidade do driver. Para os cinco bancos deste guia, há drivers maduros no npm. O critério pesa mais em bancos menos populares.
Se você ainda está decidindo o banco em geral, sem foco no Node.js, veja qual banco de dados escolher.
PostgreSQL com Node.js#
O PostgreSQL é relacional, tem transações completas, extensões e o tipo jsonb, que guarda JSON com suporte a índices. Isso permite misturar colunas fixas com um campo flexível na mesma tabela, o que cobre boa parte dos casos em que alguém escolheria um banco de documentos.
O driver mais usado é o pg (node-postgres). A documentação recomenda criar um único pool para a aplicação e usar pool.query sempre que possível, porque assim o driver devolve a conexão ao pool sozinho:
// npm install pg
import pg from "pg";
// Um pool para a aplicação inteira, criado uma vez
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
export async function buscarUsuario(email) {
// $1 é um parâmetro: o driver envia o valor separado, sem risco de SQL injection
const { rows } = await pool.query(
"SELECT id, nome, criado_em FROM usuarios WHERE email = $1",
[email],
);
return rows[0] ?? null;
}
export async function contarUsuarios() {
const { rows } = await pool.query("SELECT count(*) AS total FROM usuarios");
return Number(rows[0].total); // count(*) é int8 e chega como string
}Prós: transações e integridade, jsonb para dados flexíveis, colunas json/jsonb chegam como objetos JavaScript e datas chegam como Date.
Contras e armadilhas: o driver devolve int8 (incluindo o resultado de count(*)) como string, porque um inteiro de 64 bits pode passar do limite seguro do Number. Abrir um Client novo a cada requisição em vez de usar o pool esgota as conexões do servidor; se isso já aconteceu, veja o erro "too many connections".
MySQL com Node.js#
O MySQL também é relacional, muito popular em hospedagens e no ecossistema PHP, com tutoriais e ferramentas em abundância. No Node.js, o driver mais usado é o mysql2, que tem API com Promises (mysql2/promise), pool de conexões e prepared statements.
Prós: familiar para quem vem de PHP ou de hospedagem compartilhada, transações com o mecanismo InnoDB, amplo suporte em ORMs.
Contras: menos tipos avançados que o PostgreSQL, e algumas diferenças de comportamento entre versões e modos SQL. Para um projeto novo sem restrições, a diferença prática costuma ser pequena. A comparação detalhada está em PostgreSQL ou MySQL.
MongoDB com Node.js#
O MongoDB guarda documentos parecidos com JSON em collections, sem esquema obrigatório. No Node.js, um documento chega como objeto JavaScript, o que torna o primeiro contato muito confortável. O driver oficial é o pacote mongodb; o Mongoose é uma camada popular por cima dele, que adiciona esquemas e validação.
// npm install mongodb
import { MongoClient } from "mongodb";
// O cliente mantém um pool interno: crie um só e reutilize
const client = new MongoClient(process.env.MONGODB_URI);
const configs = client.db("meubot").collection("configs");
// Grava ou atualiza a configuração de um servidor do Discord
export async function salvarConfig(guildId, config) {
await configs.updateOne({ guildId }, { $set: config }, { upsert: true });
}
export async function lerConfig(guildId) {
return configs.findOne({ guildId });
}Prós: ótimo quando você lê e grava o objeto inteiro de uma vez (configuração por servidor de um bot, perfis com campos opcionais, catálogos com atributos diferentes). Mudar o formato não exige migração.
Contras: sem esquema, a validação fica com você (no código, no Mongoose ou em regras do banco). Relações e transações entre vários documentos existem, mas pesam mais do que num banco relacional. O passo a passo da conexão está em como conectar MongoDB ao Node.js.
Redis com Node.js#
O Redis guarda dados em memória, com acesso por chave, e responde muito rápido. Raramente é o único banco: o papel clássico é ser o segundo, ao lado de um PostgreSQL ou MongoDB, para cache, sessões, filas, contadores e limites de requisição. O cliente oficial no npm é o pacote redis (node-redis):
// npm install redis
import { createClient } from "redis";
const redis = await createClient({ url: process.env.REDIS_URL })
.on("error", (err) => console.error("Erro no Redis", err))
.connect();
// Cooldown de 10 segundos por usuário: NX só grava se a chave ainda não existir
export async function emCooldown(userId) {
const resultado = await redis.set(`cooldown:${userId}`, "1", {
expiration: { type: "EX", value: 10 },
condition: "NX",
});
return resultado === null; // null = a chave já existia
}Prós: latência muito baixa, expiração automática de chaves, estruturas prontas (listas, conjuntos, hashes).
Contras: os dados precisam caber na memória, e o que não foi persistido pode se perder numa queda. Não use como banco principal de dados que você não pode perder. Mais em o que é Redis.
E o SQLite?#
O SQLite é um banco inteiro dentro de um arquivo, sem servidor. Para Node.js há duas rotas: o pacote better-sqlite3, muito usado, e o módulo nativo node:sqlite, incluído nas versões recentes do Node (confira na documentação da sua versão o nível de estabilidade dele).
Prós: zero configuração, ótimo para protótipos, scripts, ferramentas de linha de comando e bots pequenos de um processo.
Contras: um escritor por vez, e o arquivo fica no disco da máquina. Se você roda várias réplicas, ou se outro serviço precisa ler os mesmos dados, migre para um banco cliente-servidor.
Qual banco escolher para cada cenário?#
| Cenário | Recomendação | Driver |
|---|---|---|
| API REST com usuários, pedidos e pagamentos | PostgreSQL | pg |
| Site ou sistema legado em PHP | MySQL | mysql2 |
| Bot do Discord com economia, níveis e inventário | PostgreSQL | pg |
| Bot com configuração por servidor e campos opcionais | MongoDB ou PostgreSQL com jsonb |
mongodb ou pg |
| Cache, sessões, filas, rate limit, cooldown | Redis, ao lado do banco principal | redis |
| Protótipo, CLI ou app de um processo só | SQLite | better-sqlite3 ou node:sqlite |
Em dúvida, comece pelo PostgreSQL. Se você já usa TypeScript e quer tipos gerados a partir do esquema, um ORM como Prisma ou Drizzle por cima do PostgreSQL ou do MySQL é um bom acréscimo, mas não um requisito. Depois de escolher, o próximo passo é hospedar a aplicação Node.js e o banco no mesmo lugar, para manter a latência baixa.
Como fazer isso na Square Cloud#
A Square Cloud oferece hospedagem de MongoDB, PostgreSQL, MySQL e Redis a partir do plano Standard (o Hobby não inclui bancos). Você cria o banco no painel, escolhendo nome, memória e motor, e ele é provisionado em segundos no mesmo datacenter das suas aplicações, com latência média de cerca de 1 ms entre eles.
Na prática: copie a URL de conexão completa que o painel entrega (ela aparece uma vez na criação; redefinir a senha mostra de novo) para uma variável de ambiente da aplicação Node.js, como DATABASE_URL ou MONGODB_URI. Baixe o certificado: o TLS é obrigatório, o driver precisa confiar na CA baixada e, no PostgreSQL e no MongoDB, também apresentar o certificado .pem. No Redis, a URL usa rediss://. Mantenha um único pool para o processo inteiro, já que cada banco aceita até 512 conexões e não há pooler na frente.
O PostgreSQL é o nativo, sem extensões, e o Redis tem persistência. Você tira snapshots manuais quando quiser, e todo plano com bancos inclui também um snapshot automático diário. Um snapshot pode ser restaurado no mesmo banco, em outro do mesmo motor ou num banco novo, ou baixado como .zip. Veja as opções em Bancos de dados.
Hospedagem de bancos
MongoDB, PostgreSQL, MySQL e Redis no mesmo datacenter do app
Perguntas frequentes
Qual é o melhor banco de dados para Node.js?
Não existe um único melhor, mas PostgreSQL atende a maioria dos projetos: é relacional, tem transações, guarda JSON com o tipo jsonb e o driver pg é maduro. MongoDB é a alternativa quando os dados são documentos de formato variável.
MongoDB combina mais com Node.js porque usa JSON?
Os documentos do MongoDB viram objetos JavaScript sem conversão, o que é confortável. Mas o PostgreSQL também devolve colunas jsonb como objetos no driver pg. Escolha pelo formato dos dados e pela necessidade de transações, não pela linguagem.
Preciso de um ORM para usar banco de dados no Node.js?
Não. Os drivers oficiais (pg, mysql2, mongodb, redis) bastam e ensinam o que acontece por baixo. ORMs como Prisma e Drizzle ajudam com tipos e migrações, e o Mongoose faz o papel equivalente para MongoDB.
Por que o count(*) do PostgreSQL chega como string no Node.js?
Porque count(*) devolve int8, um inteiro de 64 bits, e o driver pg devolve int8 como string para não perder precisão acima do limite seguro dos números do JavaScript. Converta com Number() quando souber que o valor é pequeno.
Mais em Bancos de dados
Ver todos os 24 artigos- Quanto custa um banco de dados na nuvem?Um banco de dados na nuvem custa de zero a centenas de dólares por mês. Veja o que define o preço: instância, disco, tráfego, snapshots e como estimar o seu.
- Como hospedar um banco de dados (e conectar sua aplicação)Para hospedar um banco de dados, escolha o motor, crie a instância, guarde a string de conexão em variável de ambiente e teste a conexão. Veja o passo a passo.
- O que é Redis e para que serveRedis é um banco de dados em memória que guarda pares chave-valor e estruturas de dados. Veja como funciona, para que serve e quando não usar.
- Como fazer backup do banco de dados (MySQL, PostgreSQL, MongoDB)Faça backup de MySQL, PostgreSQL e MongoDB com mysqldump, pg_dump e mongodump, e restaure o dump. Veja os comandos, como verificar e os erros comuns.