A Resposta Curta
A pergunta "Flow ou Apex" recebe uma resposta incorreta quando analisada pela conveniência de escrita ou pela disponibilidade de desenvolvedores. A resposta certa depende de quatro fatores técnicos: quantas transações são processadas por vez, se a lógica exige atomicidade completa, a complexidade das condições e ramificações, e quem fará a manutenção do componente daqui a um ano. O Flow é a escolha declarative padrão para a maioria das automações de negócios – mas há pontos de transição claros onde continuar com o Flow cria um risco operacional, e não apenas um "código menos elegante".
Este artigo aborda a decisão de escolha em si: como identificar antecipadamente se a lógica justifica o uso de Apex e como evitar que a escolha seja feita por padrão, e não por discernimento. A questão da limpeza de Flows e processos de automação existentes que já se acumularam como dívida técnica é discutida em um artigo separado e não faz parte desta discussão.
O que de Fato Distingue os Dois no Nível da Plataforma
Flow é um declarative engine que é traduzido em tempo de execução para instruções que realizam DML e SOQL em nome do usuário, enquanto Apex é um código compilado que roda sob os mesmos Governor Limits, mas com controle direto da ordem das operações. A primeira diferença prática é a Bulkification: um desenvolvedor Apex constrói explicitamente um loop que coleta todos os registros em um único array e executa um DML único, enquanto no Flow é fácil construir um Loop que executa uma operação DML ou uma consulta em cada iteração separadamente — um padrão que atinge o limite de 101 consultas permitidas muito mais rapidamente.
A segunda diferença é o controle transacional. O Apex permite Savepoint e Database.rollback para cancelamento parcial, tratamento de DmlException no nível de registro individual via Database.insert(list, false), e lógica condicional complexa sem limite de profundidade de ramificações. No Flow, o tratamento de erros é definido no nível de Fault Path para cada elemento, e isso funciona bem para cenários lineares, mas se torna difícil de rastrear quando há mais do que algumas rotas de falha paralelas.
Estrutura de Decisão: Quatro Testes Antes de Escolher uma Ferramenta
Teste de Volume
Regra prática: se o processo roda em um único registro como resultado de uma ação do usuário (criação de um Lead, mudança de status de oportunidade), o Flow é quase sempre suficiente. Se o processo roda em dezenas a milhares de registros de uma vez — atualização periódica, processamento de um lote vindo de uma integração, limpeza de dados agendada — Apex com Batchable ou Queueable é a escolha segura, pois oferece controle total sobre a Bulkification e gerenciamento de Governor Limits frente a um volume variável.
Teste de Atomicidade
Deve-se perguntar: se parte da atualização falhar, a outra parte pode permanecer salva? Se a resposta for "não" — por exemplo, atualização de um pedido e criação de um registro de fatura que devem ocorrer juntos — Apex com Savepoint é a maneira correta de garantir isso. O Flow não oferece um rollback completo entre elementos sem a construção manual e complexa de lógica de compensação.
Teste de Complexidade das Ramificações
Um Flow com mais de 6-8 Decision Elements aninhados torna-se difícil de ler e caro de testar, mesmo que cada ramificação individual seja simples. Quando a complexidade da lógica de negócios excede isso, escrever essa mesma lógica como uma função Apex documentada com testes de unidade (@isTest) geralmente é mais barato de manter, mesmo que o tempo inicial de escrita seja maior.
Teste de Manutenção e Propriedade
Deve-se perguntar quem fará a manutenção do componente daqui a um ano, não quem o está construindo agora. Se a equipe de Admin for a responsável por atualizar as regras de negócios de forma contínua — como a alteração de condições de desconto ou valores limite — o Flow é preferível, mesmo que o Apex seja tecnicamente "mais limpo", pois é acessível para atualização sem um ciclo de implantação. Se as alterações exigem conhecimento do esquema de dados e testes de regressão, o Apex é a escolha certa, mesmo que haja apenas uma pequena equipe de desenvolvimento para mantê-lo.
Tabela de Decisão
| Critério | Escolha Flow | Escolha Apex |
|---|---|---|
| Volume de registros em uma única transação | Até algumas dezenas | Centenas a milhares |
| Exigência de Atomicidade entre vários objetos | Não crítica | Crítica — Rollback completo necessário |
| Número de ramificações de decisão | Até aproximadamente 6-8 | Acima disso, ou lógica recursiva |
| Frequência de mudança das regras de negócios | Frequente, por Admin | Rara, exige testes de regressão |
| Necessidade de chamar API externa complexa | Chamada única simples (HTTP Callout) | Lógica de Retry, autenticação complexa ou Batch |
| Exigência de testes automatizados (CI) | Limitada | Completa, @isTest com Coverage |
| Integração com Scheduled Job regular | Não diretamente adequado | Natural via Schedulable |
Cenário de Exemplo: Empresa de Equipamentos Médicos com Processo de Aprovação de Pedidos
Uma empresa de equipamentos médicos de médio porte com cerca de 40 representantes de vendas operava um Flow para o processo de aprovação de pedidos: verificação de estoque, cálculo de desconto, criação de registro de aprovação e envio de notificação ao gerente. No início, funcionou bem para um único pedido. Após seis meses, um novo cenário foi adicionado — importação em lote de pedidos de um arquivo de integração com o ERP, que cria entre 200 e 800 pedidos simultaneamente.
O Flow, que era acionado por um Record-Triggered Flow no nível "para cada registro", executava uma consulta de verificação de estoque dentro de cada execução separadamente. Com a importação de 500 pedidos, o sistema excedeu o limite de 100 consultas em uma única transação, e os pedidos falharam sem uma mensagem de erro clara para o usuário. A equipe identificou que o problema não era no Flow em si, mas na adequação entre um processo projetado para um único registro e um cenário de volume que não existia no momento da construção.
A solução não foi abandonar o Flow. A equipe dividiu a lógica: o Flow permaneceu responsável pelo processo manual de um único pedido (teste de baixo volume, necessidade de atualização frequente das regras de desconto pelo Admin), enquanto o processo de importação em lote foi transferido para um Apex Batch Job que realiza Bulkification completa, verifica o estoque em uma única consulta concentrada e executa um DML único para todos os registros. Os dois mecanismos chamam a mesma camada de lógica de negócios compartilhada (uma única Apex Class que o Flow também chama via Invocable Method), para que a regra de desconto não seja mantida duas vezes.
Riscos Comuns e Ações Preventivas
| Risco | Como isso se manifesta na prática | Ação preventiva |
|---|---|---|
| Flow sobre volume que cresce gradualmente | O processo funcionou por seis meses e então falhou silenciosamente por Governor Limits | Avaliar o volume esperado antecipadamente e planejar um ponto de transição para Apex antes de atingir o limite |
| Duplicidade de lógica de negócios em Flow e Apex | Dois locais calculam o desconto de forma diferente | Centralizar o cálculo de negócios em uma camada Apex comum que o Flow também chame |
| Trigger Order inesperado | Vários Flows e Triggers no mesmo objeto entram em conflito | Um Trigger Handler centralizado em Apex para cada objeto crítico |
| Tratamento parcial de erros em Flow complexo | Parte dos registros é atualizada e parte não, sem visibilidade | Transferir processos que exigem Atomicidade para Apex com Savepoint |
| Apex sem testes suficientes | Uma pequena alteração quebra um processo crítico na próxima implantação | Exigir Coverage real e não apenas uma porcentagem formal, incluindo cenários de falha |
Checklist para Decisão Antes da Construção
- Volume esperado avaliado para o período de um ano, não apenas o estado atual
- Definido se o processo requer Atomicidade entre vários objetos
- Contadas as ramificações de decisão esperadas na lógica
- Confirmado quem fará a manutenção do componente e com que frequência as regras mudarão
- Verificado se já existe lógica semelhante em Apex ou em outro Flow no mesmo objeto
- Definido o Trigger Order se houver vários mecanismos de automação no objeto
- Se Apex for escolhido — cenários de teste definidos, incluindo falha parcial
- Se Flow for escolhido — Fault Path definido para cada elemento crítico
Como Isso se Conecta à Arquitetura Mais Ampla
A escolha da ferramenta certa para uma automação individual é apenas uma camada em uma imagem mais ampla da arquitetura de CRM, na qual tanto o modelo de dados quanto as permissões afetam o que o Flow ou o Apex podem tocar. Quando a automação cruza a fronteira para uma organização externa — por exemplo, verificação de estoque com o ERP em tempo real — a escolha entre Flow e Apex também se encaixa nas considerações sobre padrões de integração e na questão de como Salesforce se conecta ao ERP em termos de latência e tratamento de falhas.
Em organizações que operam vários Orgs, também é necessário verificar se a lógica de negócios é idêntica em todos eles — um tópico discutido no guia Single Org vs. Multi Org e que afeta a questão de valer a pena centralizar a lógica em um Apex Package compartilhado.
Resumo
A escolha entre Flow e Apex não é uma questão de habilidade da equipe ou gosto pessoal, mas sim o resultado de quatro testes técnicos: volume, atomicidade, complexidade das ramificações e frequência de mudança. O Flow é o declarative default para a maioria das automações que interagem com um único registro e mudam com alta frequência. O Apex é necessário quando há um volume significativo, quando é preciso controle total da transação ou quando a complexidade lógica excede o limite que ainda pode ser mantido por meio de uma interface declarativa. Uma organização que estabelece esses testes como parte de seu processo de trabalho — e não os deixa para o julgamento ad-hoc de cada desenvolvedor — economiza a maioria dos casos em que uma automação que funcionou bem no início se quebra silenciosamente quando o volume cresce.
