O que são Gatilhos de Banco de Dados (beforeSave e afterSave)?

Atualizado em: agosto de 2026

Um gatilho de banco de dados é um hook de código que roda automaticamente em eventos de dados — antes do save para validar, depois dele para reagir. A ideia tem duas linhagens que compartilham um princípio: o trigger SQL clássico, código procedural vivendo dentro do motor do banco, e o hook em nível de aplicação moderno — beforeSave, afterSave, beforeDelete — JavaScript registrado por classe no backend. Ambos codificam a mesma promessa: a regra dispara para toda gravação, não importa qual cliente, SDK ou script a executou — que é exatamente o que a validação no cliente nunca pode prometer.

Principais pontos

PerguntaResposta
O princípioCódigo preso a eventos de dados — automático, por tabela/classe, todo caminho de gravação
Before =Validar · normalizar · aplicar defaults — ainda pode alterar ou abortar a gravação
After =Reagir — contar, notificar, sincronizar; a gravação já aconteceu, então seja idempotente
As duas formasTriggers SQL dentro do motor · hooks JS no processo do backend
Os bugs clássicosLógica escondida · loops infinitos de autodisparo · triggers lentos travando todo save

O modelo de hooks em ação

Uma regra de validação e sua aplicação, vistas das duas pontas — o servidor a define uma vez, e todo cliente em todo lugar a herda:

// JavaScript — Cloud Code (cloud/main.js)
// beforeSave: validate + normalize — can still change or ABORT the write
Parse.Cloud.beforeSave('Review', (req) => {
  const stars = req.object.get('stars');
  if (stars < 1 || stars > 5) throw 'Stars must be between 1 and 5';
  const comment = req.object.get('comment');
  if (comment && comment.length > 500) {
    req.object.set('comment', comment.slice(0, 497) + '…');
  }
});

// afterSave: side effects — the write already happened; be idempotent
Parse.Cloud.afterSave('Review', async (req) => {
  if (req.object.existed()) return; // count only NEW reviews, once
  await updateAverageStars(req.object.get('movie'));
});

A família completa de hooks estende a mesma forma por todo o ciclo de vida dos dados: beforeSave/afterSave, beforeDelete (bloquear a exclusão de um Album que ainda tem Photos) e afterDelete (limpar os filhos dele), mais beforeFind/afterFind para reescrever queries e remover campos dos resultados — o CRUD, embrulhado.

A forma clássica: triggers SQL

CREATE TRIGGER audit_price_change
AFTER UPDATE ON products
FOR EACH ROW                              -- nível de linha: dispara por linha afetada
WHEN (OLD.price IS DISTINCT FROM NEW.price)
EXECUTE FUNCTION log_price_change();      -- OLD e NEW guardam as duas versões

A taxonomia que todo banco compartilha, segundo as referências do PostgreSQL e do MySQL: timing — BEFORE (pode modificar NEW ou abortar), AFTER (reage à linha confirmada), INSTEAD OF (substitui a operação, principalmente em views); evento — insert, update, delete; granularidade — nível de linha versus nível de instrução (um update de 10 linhas dispara um trigger de linha 10 vezes, um de instrução uma vez). Duas semânticas que valem gravar: triggers SQL rodam dentro da mesma transação da gravação — uma falha no trigger desfaz a operação inteira — e triggers AFTER só disparam para gravações que de fato tiveram sucesso.

Before vs. after: escolhidos pelo trabalho

Before hooksAfter hooks
Pode alterar os dadosSim — mutar, aplicar default, truncarNão — já foi gravado
Pode abortar a gravaçãoSim — lance um erro, e o save falhaNão
Certo paraValidação, normalização, campos computadosContadores, notificações, sincronização, auditoria
Errado paraEfeitos colaterais — se o save falhar depois, o efeito já disparouQualquer coisa que deveria ter bloqueado a gravação
Comportamento na falhaRejeita a operação, erro para o clienteMuitas vezes fire-and-forget — erros caem nos logs
DisciplinaRápido — ele bloqueia todo saveIdempotente — pode rodar de novo

Os corolários que nenhum explicador enuncia: um efeito colateral em um before-hook é um bug por construção (o e-mail sai, e então o save falha), e um after-hook que não é idempotente é um contador duplicado esperando um retry. Em sistemas de hooks como o do Back4app, o afterSave completa depois que o cliente já recebeu a resposta — reações são assíncronas por design, então suas falhas precisam ser toleráveis e logadas.

Ciclo de vida da gravação através dos hooks before e afterUma gravação vinda de qualquer cliente passa primeiro pelo hook before, que pode validá-la, modificá-la ou abortá-la. Se permitida, o banco de dados confirma a gravação, e o hook after então reage com efeitos colaterais como contadores, notificações e webhooks, que precisam ser idempotentes porque podem rodar mais de uma vez.

throw

permite (talvez modificado)

Qualquer cliente
SDK · REST · script

beforeSave
valida · normaliza

Save rejeitado —
erro para o cliente

Gravação confirmada

afterSave
efeitos colaterais, idempotentes

Contadores · notificações ·
webhooks de saída

Uma gravação vinda de qualquer cliente passa primeiro pelo hook before, que pode validá-la, modificá-la ou abortá-la. Se permitida, o banco de dados confirma a gravação, e o hook after então reage com efeitos colaterais como contadores, notificações e webhooks, que precisam ser idempotentes porque podem rodar mais de uma vez.

Hooks vs. triggers SQL

Hooks de aplicação (beforeSave/afterSave)Triggers SQL
LinguagemJavaScript + o SDK e o ecossistema inteirosSQL / dialetos procedurais de SQL
Chamadas externasSim — APIs, push, webhooksEssencialmente não — e nem deveriam
Vive emSeu codebase: versionado, testável, deployadoO schema: dentro do banco de dados
TransaçãoBefore-hooks são o portão da gravação; after-hooks rodam pós-respostaMesma transação — a falha desfaz tudo
Vale paraToda requisição que passa pela API do backendToda gravação na tabela, venha de onde vier
Ponto cegoGravações diretas no banco passam por foraLógica invisível aos debuggers da aplicação

A última linha é a simetria honesta: a garantia de cada forma está limitada à sua camada. Um trigger SQL pega até uma sessão psql renegada, mas esconde lógica do ferramental da aplicação; um hook em nível de API cobre todo caminho de cliente através do backend, mas não o acesso cru ao banco — e é por isso que plataformas donas do gateway de API (todo o tráfego flui por ele) ficam, na prática, com o melhor dos dois. A nota de rodapé sobre ORMs entra aqui também: hooks de ORM só disparam através do ORM — operações em massa e SQL cru passam reto por eles.

As armadilhas, com honestidade

Lógica escondida é o clássico: um desenvolvedor depura o próprio código por horas enquanto um trigger reescreve valores em silêncio — triggers são invisíveis no ponto de chamada, então documente-os e mantenha-os poucos. Loops infinitos: um trigger gravando na própria tabela dispara a si mesmo de novo (e um afterSave salvando o próprio objeto também); proteja-se checando o que mudou, e dê à recursão uma condição de parada antes que ela encontre uma por você. Custo síncrono: before-hooks moram dentro da latência de toda gravação — um hook de 200 ms deixa todo save 200 ms mais lento, e gravações em massa multiplicam os disparos por linha pela contagem de linhas. Cadeias em cascata: triggers que disparam triggers que disparam triggers transformam um insert em um projeto de arqueologia. A regra guarda-chuva de décadas de prática: triggers aplicam regras; no momento em que um começa a orquestrar um workflow, mova o workflow para funções ou jobs e deixe o trigger apenas enfileirar.

Casos de uso comuns

  • Validação que todo cliente obedece — a regra de estrelas-entre-1-e-5, aplicada contra requisições forjadas e SDKs futuros igualmente.
  • Trilhas de auditoria — quem mudou o quê, quando, escritas pelo próprio evento em vez de por clientes cooperativos.
  • Contadores desnormalizados e campos computados — médias, contagens e duplicatas amigáveis à busca mantidas verdadeiras no momento da gravação.
  • Integridade em cascata — recusar exclusões com filhos, ou limpar os filhos depois.
  • Efeitos colaterais reativos — um afterSave disparando uma notificação push ou um webhook de saída: o evento de banco de dados virando evento de integração.

Qual hook onde? Matriz de decisão

O trabalhoO hook
Rejeitar dados ruinsbeforeSave — lance um erro
Trim, default, canonicalizarbeforeSave — mute o objeto
Atualizar um contador ou agregadoafterSave — com idempotência
Notificar uma pessoa ou sistemaafterSave → push / webhook / fila
Bloquear exclusões perigosasbeforeDelete
Limpar depois de exclusõesafterDelete
Aplicar escopo de query por usuáriobeforeFind
Reação longa ou lentaafterSave enfileira um job — nunca faz o trabalho inline

Limitações e trade-offs

  • Invisibilidade é o preço da automaticidade. Lógica que ninguém chama é lógica que ninguém lembra; nomes, docs e code review mantêm a mágica auditável.
  • Hooks têm o escopo da sua camada. Hooks de API não veem gravações diretas no banco; triggers SQL não perdem nada, mas se escondem do seu ferramental — saiba qual ponto cego você escolheu.
  • A latência de gravação é o orçamento. Todo before-hook gasta dele; meça hooks como você mede queries.
  • After-hooks são eventualmente consistentes. Contadores atrasam milissegundos e podem disparar em dobro — projete as leituras (e os retries) de acordo.
  • Triggers não substituem constraints. Índices únicos, chaves estrangeiras e ACLs aplicam mais barato e mais cedo; triggers começam onde as regras declarativas param.

Gatilhos de Banco de Dados no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. Gatilhos aqui são a família de eventos de dados do Cloud Code: registre Parse.Cloud.beforeSave('Review', …) uma vez — as abas de código mostram o padrão inteiro — e a regra vale para toda gravação que chega por REST, GraphQL, qualquer SDK ou o dashboard, porque o gateway de API é o único caminho até os dados. Os hooks recebem contexto rico (request.object, request.original, request.user, status de master key), então a validação pode diferir para admins, o beforeFind pode aplicar escopo por usuário em cima das ACLs, e os after-hooks têm o ecossistema JavaScript inteiro para as reações que triggers SQL não alcançam — notificações push, webhooks de saída, enfileiramento de jobs. Deployado com o seu código, versionado no git, testável como qualquer função: a garantia do trigger, sem a arqueologia do trigger.

Perguntas frequentes

O que é um trigger de banco de dados?

É código procedural que executa automaticamente quando um evento de dados — insert, update, delete — ocorre em uma tabela ou classe específica. A forma clássica vive dentro do banco SQL; a forma moderna, em nível de aplicação, é uma função hook como beforeSave ou afterSave que o backend roda em volta de toda gravação.

Qual a diferença entre triggers BEFORE e AFTER?

Capacidade e timing. O BEFORE roda antes da gravação e pode validar, modificar os dados que chegam ou abortar a operação por completo. O AFTER roda depois que a gravação teve sucesso — não pode mudar o que aconteceu, só reagir: registrar, contar, notificar. O AFTER nunca dispara para gravações que falharam.

Qual a diferença entre um trigger e uma stored procedure?

A invocação. Uma stored procedure é chamada explicitamente, recebe parâmetros e retorna resultados. Um trigger nunca é chamado — ele dispara automaticamente quando seu evento ocorre, sem parâmetros, preso a uma tabela. A mesma maquinaria procedural, com o modelo de ativação oposto.

A lógica deve ficar em triggers ou no código da aplicação?

O consenso é um híbrido: triggers (ou hooks) para regras que precisam valer em todo caminho de gravação — validação, integridade, auditoria — e serviços da aplicação para workflows complexos. Hooks em nível de aplicação são o meio-termo moderno: as garantias do trigger, uma linguagem de verdade e controle de versão.

Triggers prejudicam a performance?

Eles rodam de forma síncrona dentro do caminho de gravação, então um trigger lento deixa todo save lento, e triggers em nível de linha se multiplicam em operações em massa — um update de cem mil linhas dispara cem mil vezes. Mantenha os before-hooks enxutos e empurre reações lentas para after-hooks ou jobs em segundo plano.

Um trigger pode causar um loop infinito?

Famosamente — um trigger que grava na própria tabela dispara a si mesmo de novo, e um afterSave que salva o objeto que acabou de tratar entra em recursão até algo quebrar. Proteja-se checando o que de fato mudou antes de gravar, e nunca salve de novo o objeto disparador dentro do próprio after-hook sem uma condição de parada.

Triggers podem chamar serviços externos?

Triggers SQL essencialmente não podem — nem deveriam — alcançar nada fora do banco. Essa é a vantagem de cartaz dos hooks em nível de aplicação: um afterSave em JavaScript pode enviar uma notificação push, chamar qualquer API ou disparar um webhook de saída, porque roda no processo do backend com o ecossistema inteiro disponível.

Para que serve o beforeSave?

Para os três trabalhos que exigem rodar antes da gravação: validação (lance um erro e o save falha, para qualquer cliente), normalização (trim, truncamento, canonicalização de campos) e defaults ou valores computados. Efeitos colaterais não pertencem ali — se o save falhar depois, o efeito já aconteceu.

Termos relacionados

Compare com

Leitura adicional

Pronto para construir seu backend?

Comece seu projeto no Back4app em minutos — banco de dados, autenticação, APIs e Cloud Code incluídos. Sem cartão de crédito.

Escrito e revisado por Back4app Engineering, Back4app Engineering · Publicado em 2026-08-21