{}FireSchema

Melhores Práticas Firestore: 15 Regras que Todo Desenvolvedor Deve Conhecer

Modelagem de dados, consultas, segurança e otimização de custos para projetos Firebase

Desenvolvendo com Firestore? Estas 15 regras vão te poupar dos erros mais comuns. Se você está começando seu primeiro projeto Firebase ou escalando um existente, essas melhores práticas cobrem tudo, desde modelagem de dados até otimização de custos — aprendidas de aplicações reais em produção.

Regras de Modelagem de Dados

Como você estrutura seus dados determina todo o resto — desempenho de consultas, custos e manutenibilidade. Acerte isso primeiro.

1. Prefira coleções planas em vez de aninhamento profundo

Subcoleções profundamente aninhadas tornam as consultas mais difíceis e criam acoplamento forte. Mantenha sua hierarquia de coleções rasa — geralmente 1-2 níveis de profundidade. Use coleções de nível raiz com referências a documentos em vez de aninhar tudo sob um pai. Por exemplo, armazene orders como uma coleção raiz com um campo userId em vez de aninhar em users/{id}/orders — a menos que você só consulte pedidos por usuário.

2. Desnormalize dados para desempenho de leitura

No SQL você normaliza para evitar duplicação. No Firestore, você desnormaliza para evitar múltiplas leituras. Se sua interface mostra o nome de um usuário ao lado de cada comentário, armazene authorName diretamente em cada documento de comentário — não force uma leitura separada na coleção users. Aceite o trade-off: escritas são mais complexas, mas leituras são rápidas e baratas.

3. Use subcoleções para relacionamentos um-para-muitos ilimitados

Quando um documento pode ter centenas ou milhares de itens relacionados (mensagens em um chat, pedidos de um usuário), use subcoleções. Diferente de arrays dentro de documentos, subcoleções podem conter itens ilimitados e suportam consultas eficientes com paginação. Exemplo: chats/{chatId}/messages/{messageId}.

4. Mantenha documentos abaixo de 20 KB para desempenho ideal

O limite rígido do Firestore é 1 MB por documento, mas mire em menos de 20 KB. Documentos grandes desperdiçam banda quando você só precisa de alguns campos — e o Firestore cobra por leitura de documento independente do tamanho. Se um documento está crescendo, divida-o em subcoleções ou uma coleção separada.

5. Evite arrays para dados consultáveis

Arrays no Firestore têm limitações: você não pode atualizar elementos individuais, consultas array-contains só suportam uma por consulta, e arrays não escalam bem além de algumas centenas de itens. Para tags ou categorias use array-contains, mas para relacionamentos ou listas crescentes, use subcoleções ou campos de mapa.

Otimização de Consultas

Consultas Firestore são rápidas por design, mas só se você trabalhar com suas restrições — não contra elas.

6. Crie índices compostos proativamente

O Firestore requer um índice para cada padrão de consulta único. Em vez de esperar mensagens de erro, planeje seus índices antecipadamente. Defina-os em firestore.indexes.json e publique com firebase deploy --only firestore:indexes. Cada combinação where + orderBy precisa de seu próprio índice composto.

7. Use paginação baseada em cursor, não offsets

Nunca use paginação baseada em offset no Firestore — ainda lê (e cobra por) todos os documentos ignorados. Em vez disso, use startAfter() com o último documento da página anterior. Isso é mais rápido e barato, pois o Firestore só lê os documentos que você realmente precisa.

8. Limite resultados de consulta explicitamente

Sempre adicione .limit() às suas consultas. Sem ele, o Firestore retorna todos os documentos correspondentes — que podem ser milhões. Mesmo que você pense que uma coleção é pequena hoje, não será em seis meses. Um bom padrão é 20-50 documentos por consulta.

9. Evite ler coleções inteiras

Se você se encontrar fazendo collection('users').get() sem filtros, seu modelo de dados precisa ser repensado. Use consultas de agregação (count(), sum()) para análises, e sempre filtre com where() para consultas de exibição. Ler todos os documentos é a causa número 1 de contas inesperadas do Firestore.

Padrões de Regras de Segurança

As regras de segurança do Firestore são sua única validação server-side. Erre nisso e todo seu banco de dados está exposto.

10. Sempre valide tipos de campo nas regras

Não apenas verifique se um campo existe — valide seu tipo. Um cliente malicioso pode enviar age: "not a number" se você só verificar request.resource.data.age != null. Use is string, is number, is bool para impor tipos no nível das regras de segurança.

11. Use regras granulares por coleção

Nunca use allow read, write: if true no nível do banco de dados. Escreva regras específicas para cada coleção: quem pode ler, quem pode criar, quem pode atualizar, quem pode deletar. Comece com tudo negado e abra acesso incrementalmente. Use padrões match para subcoleções.

12. Nunca confie em dados do lado do cliente

O cliente pode enviar qualquer dado que quiser. Valide campos obrigatórios, verifique tipos de dados, imponha valores de enum e verifique que campos de referência apontam para documentos reais. Use request.auth para verificar que o usuário é quem alega ser, e resource.data para comparar com valores existentes.

Otimização de Custos

A precificação do Firestore é baseada em leituras, escritas e armazenamento. Pequenas mudanças em como você consulta podem ter grandes impactos na sua conta.

13. Agrupe escritas para reduzir operações

Use writeBatch() ou runTransaction() para combinar múltiplas escritas em uma única operação. Um lote de 500 escritas custa o mesmo que 500 escritas individuais em termos de operações, mas reduz viagens de rede e garante atomicidade. Limite lotes a 500 operações no máximo.

14. Faça cache de documentos frequentemente lidos

O SDK cliente do Firestore tem persistência offline integrada — habilite-a. Para aplicações server-side, implemente uma camada de cache (Redis, in-memory) para documentos que mudam raramente mas são lidos constantemente, como configuração do app ou perfis de usuário. Cada leitura em cache é uma leitura que você não paga.

15. Use consultas de agregação em vez de ler todos os docs

Precisa de uma contagem de documentos? Use countQuery() em vez de buscar todos os documentos e contar no cliente. Consultas de agregação do Firestore (count(), sum(), average()) leem entradas de índice em vez de documentos completos, custando cerca de 1/1000 por entrada.

Bônus: Documente Sua Estrutura de Banco de Dados

Todas essas melhores práticas são inúteis se sua equipe não consegue encontrá-las. À medida que seu banco de dados Firestore cresce, acompanhar estruturas de coleções, tipos de campos e regras de validação se torna um desafio. JSON Schema oferece uma forma padronizada de descrever sua estrutura de banco de dados — e ferramentas como FireSchema transformam esses schemas em documentação interativa e navegável que toda sua equipe pode consultar.

💡 Dica: Crie um arquivo .schema.json para cada coleção documentando seus campos, tipos e regras de validação. Isso se torna a fonte única de verdade da sua equipe.

Próximos Passos

Continue aprendendo sobre Firestore e documentação de banco de dados:

Experimentar FireSchema

Guia de Início Rápido