Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

localStorage no Node.js: configs e cache local

Atualizado em: 22 de outubro de 2026

Terminal Linux usado em desenvolvimento e administração de aplicações Node.js

O localStorage no Node.js oferece uma implementação compatível com a Web Storage API para guardar pares de chave e valor em um arquivo local. A proposta parece simples: usar a mesma interface conhecida do navegador para persistir pequenas configurações, estados de ferramentas, caches leves e preferências em aplicações executadas fora do browser.

Apesar da familiaridade, o comportamento no servidor exige cuidado. Os dados são compartilhados por todo o processo, não por usuário ou requisição, ficam armazenados sem criptografia e possuem limite de tamanho. Em APIs multiusuário, usar localStorage como se cada cliente tivesse seu próprio espaço pode causar vazamento de dados entre requisições.

Neste guia, você aprenderá como habilitar localStorage, definir o arquivo de persistência, usar a interface Storage, organizar chaves, lidar com quota, concorrência, testes, segurança e decidir quando preferir SQLite ou outro armazenamento.

Disponibilidade

Em versões atuais do Node.js, a implementação é uma API em fase de estabilização. Consulte a documentação oficial de localStorage e fixe uma versão mínima do runtime antes de depender do recurso.

O armazenamento é habilitado apontando um arquivo na linha de comando:

node --localstorage-file=.data/local-storage.json app.js

Sem o arquivo configurado, versões recentes podem lançar uma DOMException ao acessar o global. Isso evita a falsa impressão de que os dados seriam persistidos automaticamente.

Primeiro uso

localStorage.setItem('theme', 'dark');
console.log(localStorage.getItem('theme')); // dark

Os valores sempre são armazenados como strings. Objetos precisam ser serializados explicitamente.

const settings = {
  language: 'pt-BR',
  pageSize: 25
};

localStorage.setItem('settings', JSON.stringify(settings));

Lendo JSON com segurança

function readJson(key, fallback) {
  const raw = localStorage.getItem(key);
  if (raw === null) return fallback;

  try {
    return JSON.parse(raw);
  } catch {
    return fallback;
  }
}

Não assuma que o arquivo nunca será corrompido. Uma atualização incompleta, edição manual ou versão antiga do formato pode tornar o JSON inválido.

Interface Storage

A API possui os métodos clássicos:

  • getItem(key);
  • setItem(key, value);
  • removeItem(key);
  • clear();
  • key(index);
  • propriedade length.
for (let index = 0; index < localStorage.length; index++) {
  const key = localStorage.key(index);
  console.log(key, localStorage.getItem(key));
}

Organizando chaves

Use namespaces para evitar colisões:

const PREFIX = 'codigofacil:cli:v1:';

function storageKey(name) {
  return `${PREFIX}${name}`;
}

localStorage.setItem(storageKey('lastProject'), '/home/user/app');

Inclua versão no prefixo quando o formato pode evoluir. Assim, uma migração consegue diferenciar dados antigos.

Migração de esquema

function loadConfig() {
  const current = readJson('app:config:v2', null);
  if (current) return current;

  const legacy = readJson('app:config:v1', null);
  if (!legacy) return { theme: 'system' };

  const migrated = {
    theme: legacy.darkMode ? 'dark' : 'light'
  };

  localStorage.setItem('app:config:v2', JSON.stringify(migrated));
  return migrated;
}

Migrações devem ser idempotentes. Se o processo cair no meio, a próxima execução precisa continuar sem perder o estado válido.

Limite de quota

A implementação possui quota limitada. Ao ultrapassar o máximo, setItem() pode lançar QuotaExceededError.

try {
  localStorage.setItem(key, largeValue);
} catch (error) {
  if (error.name === 'QuotaExceededError') {
    console.error('Quota do localStorage excedida');
  } else {
    throw error;
  }
}

Não use localStorage para blobs, logs extensos, respostas de API ou filas. O limite existe para pequenos estados.

Dados sem criptografia

O arquivo é gravado em texto legível. Nunca armazene:

  • senhas;
  • refresh tokens;
  • chaves privadas;
  • segredos de API;
  • dados pessoais sensíveis;
  • cookies de sessão;
  • credenciais de banco.

Para segredos, consulte Gestão de Segredos no Node.js.

Permissões do arquivo

Mesmo para configurações não sensíveis, restrinja o diretório:

mkdir -p .data
chmod 700 .data
touch .data/local-storage.json
chmod 600 .data/local-storage.json

As permissões do sistema operacional são parte da proteção. Em containers, use volume dedicado e usuário sem privilégios.

Compartilhamento entre requisições

No servidor, existe um único localStorage para o processo. Este código é perigoso:

app.post('/preferences', async (req, res) => {
  localStorage.setItem('current-user', req.user.id);
  res.sendStatus(204);
});

Duas requisições concorrentes sobrescrevem a mesma chave. Nunca use o recurso para estado de sessão ou dados por cliente.

Para contexto por requisição, veja AsyncLocalStorage no Node.js. Apesar do nome parecido, as APIs resolvem problemas totalmente diferentes.

Concorrência

Operações de leitura e escrita podem parecer atômicas individualmente, mas sequências não são transações:

const current = Number(localStorage.getItem('counter') ?? '0');
localStorage.setItem('counter', String(current + 1));

Execuções concorrentes podem perder incrementos. Para dados que exigem consistência, use SQLite ou banco com transações.

Consulte SQLite no Node.js.

Múltiplos processos

Não trate o mesmo arquivo como banco compartilhado por vários processos. PM2, cluster, containers ou jobs simultâneos podem disputar o recurso. A API não substitui locks interprocessos e banco transacional.

Worker Threads

Verifique o comportamento da versão usada antes de compartilhar o recurso com workers. Mesmo quando o arquivo é o mesmo, coordenação de leitura e escrita exige uma estratégia explícita.

Para paralelismo, veja Worker Threads no Node.js.

Uso em CLI

Uma ferramenta de linha de comando pode guardar:

  • último workspace utilizado;
  • preferência de saída;
  • data da última verificação;
  • versão de migração;
  • flags não sensíveis.
const DEFAULTS = {
  output: 'table',
  color: true
};

const preferences = {
  ...DEFAULTS,
  ...readJson('cli:preferences:v1', {})
};

Cache leve

Para cache, inclua expiração:

function setCache(key, value, ttlMs) {
  localStorage.setItem(key, JSON.stringify({
    value,
    expiresAt: Date.now() + ttlMs
  }));
}

function getCache(key) {
  const entry = readJson(key, null);
  if (!entry) return null;

  if (entry.expiresAt <= Date.now()) {
    localStorage.removeItem(key);
    return null;
  }

  return entry.value;
}

Não use como cache distribuído. Cada instância terá seu próprio arquivo.

Limpeza

Remova chaves antigas durante inicialização:

function removeExpired(prefix) {
  const keys = [];

  for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i);
    if (key?.startsWith(prefix)) keys.push(key);
  }

  for (const key of keys) {
    const entry = readJson(key, null);
    if (entry?.expiresAt && entry.expiresAt <= Date.now()) {
      localStorage.removeItem(key);
    }
  }
}

Evite modificar o armazenamento enquanto percorre os índices, porque a ordem pode mudar. Primeiro copie as chaves.

sessionStorage

Node.js também oferece sessionStorage em versões compatíveis. Ele fica em memória e dura apenas enquanto o processo está ativo. Use para estado temporário, lembrando que não é compartilhado entre workers.

Testes isolados

Execute testes com arquivo temporário diferente por processo:

node --localstorage-file=.tmp/test-storage.json --test

Limpe antes e depois:

import test from 'node:test';
import assert from 'node:assert/strict';

test.beforeEach(() => localStorage.clear());

test('salva preferência', () => {
  localStorage.setItem('theme', 'dark');
  assert.equal(localStorage.getItem('theme'), 'dark');
});

Não edite o arquivo manualmente

A documentação não garante suporte a alterações externas. Trate o arquivo como implementação interna. Se precisa interoperar com outras ferramentas, use JSON próprio com escrita atômica ou banco.

Backup

Para preferências simples, backup pode não ser necessário. Se o estado é importante para negócio, isso já indica que localStorage provavelmente é a ferramenta errada.

Observabilidade

Registre apenas eventos gerais:

  • falha ao abrir armazenamento;
  • quota excedida;
  • migração executada;
  • entrada corrompida;
  • limpeza realizada.

Não registre valores completos quando podem conter caminhos, preferências ou informações privadas.

Quando não usar

Evite localStorage para:

  • sessões HTTP;
  • estado por usuário;
  • filas;
  • auditoria;
  • contadores concorrentes;
  • transações;
  • dados maiores que poucos megabytes;
  • compartilhamento entre pods.

Alternativas

  • arquivo JSON próprio: quando precisa controlar formato e escrita;
  • SQLite: consultas, transações e consistência local;
  • Redis: cache e estado compartilhado;
  • PostgreSQL: dados duráveis multiusuário;
  • variáveis de ambiente: configuração imutável;
  • secret manager: credenciais.

Erros comuns

  • usar sem configurar arquivo;
  • armazenar objetos sem JSON;
  • guardar segredos;
  • usar em requisições multiusuário;
  • ignorar quota;
  • compartilhar arquivo entre processos;
  • confiar em leitura-modificação-escrita;
  • editar o arquivo manualmente;
  • não versionar o formato;
  • usar como banco de produção.

Checklist

  • runtime compatível;
  • arquivo configurado;
  • diretório protegido;
  • somente dados não sensíveis;
  • chaves com namespace;
  • formato versionado;
  • tratamento de quota;
  • JSON validado;
  • testes com arquivo isolado;
  • alternativa transacional avaliada.

Conclusão

O localStorage no Node.js é conveniente para pequenas preferências e estados locais de ferramentas. A interface familiar reduz código e facilita compartilhar conceitos com aplicações web.

No servidor, porém, os dados são globais ao processo, não possuem criptografia e não oferecem transações. Use apenas para estado pequeno, não sensível e sem concorrência crítica. Quando os requisitos crescerem, migre para SQLite, Redis ou banco relacional.

Como referência de comportamento, consulte também a especificação Web Storage.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita