Gerar Thread IDs em loops no Flow destrói os limites DML do Email-to-Case
Por que usar Apex invocável para gerar tokens de e-mail sob demanda pode esgotar os limites DML da sua org e como uma abordagem assíncrona resolve o problema.

Chamar Apex invocável dentro de loops no Flow para gerar Thread IDs de Email-to-Case é um caminho certo para estourar limites DML na org. O problema não é o recurso em si, mas a granularidade da chamada. A solução passa por uma abordagem assíncrona que processa os tokens em lote, fora do contexto transacional do Flow.
O problema real: DML escondido dentro de um loop
Uma discussão recente no Salesforce Stack Exchange trouxe à tona um cenário clássico de Service Cloud que silenciosamente destrói automações em produção. O desafio era inserir o Thread ID do Email-to-Case no corpo de um e-mail disparado por Flow, mantendo o token invisível para o cliente final e sem quebrar os limites de governança da org.
O caso real envolvia o envio de e-mails para múltiplos contatos a partir de um mesmo Caso. Para garantir que as respostas voltassem ao registro correto sem abrir chamados duplicados, foi criada uma ação invocável em Apex usando o método EmailMessages.getFormattedThreadingToken(). O plano inicial era colocar essa ação dentro de um loop no Flow para gerar e capturar o token de cada destinatário individualmente.
Se você já construiu automações complexas no Salesforce, sabe que Apex invocável dentro de Loop de Flow é receita para desastre. Sempre foi, e continua sendo.
O contexto técnico que ninguém lê na documentação
O Email-to-Case depende de uma referência forte para vincular a resposta do cliente ao Caso original. Durante anos, a solução padrão era o famoso Ref ID, aquela string visível no assunto ou no rodapé da mensagem. Com as atualizações de segurança mais recentes da Salesforce, a plataforma passou a priorizar o rastreamento via cabeçalhos de e-mail (Email Headers) combinado a tokens específicos. O método getFormattedThreadingToken() existe exatamente para recuperar esse token em formato de string utilizável em templates e automações.
Até aqui, tudo parece razoável. O problema está em um detalhe que a documentação oficial menciona de forma discreta e que a maioria dos implementadores ignora até levar o erro em produção:
A pegadinha do DML implícito
Se o token de threading ainda não existir para aquele Caso específico no momento da chamada, o método getFormattedThreadingToken() força uma operação DML nos bastidores para gerá-lo e persistir no banco de dados. Essa geração não é uma leitura — é uma escrita.
Coloque essa ação invocável dentro de um loop processando dezenas de contatos e o resultado é previsível:
- Uma chamada DML por iteração do loop
- Estouro dos limites de governança da org em fluxos com volume moderado
- Falha completa do Flow, sem rollback parcial, sem registro salvo
O Flow não avisa. Ele simplesmente falha. E o log de erro aponta para limite DML excedido, sem deixar óbvio que a origem é um método aparentemente "só de leitura" chamado em loop.
A solução arquitetural: processar uma vez, armazenar, reutilizar
A correção não está em tentar otimizar o loop nem em reorganizar a ordem das ações dentro do Flow. Está em mudar a arquitetura da solução com base em um princípio simples:
Gere o dado caro uma única vez, no momento certo, de forma assíncrona. Quando a automação precisar dele, ele já deve existir.
Na prática, a abordagem recomendada funciona assim:
- Na criação do Caso, dispare um processo assíncrono — preferencialmente Queueable Apex, que chama
getFormattedThreadingToken()e salva o resultado em um campo de texto personalizado no próprio objeto Case. - No Flow de envio de e-mails, elimine completamente a ação Apex invocável. O Flow simplesmente referencia o campo personalizado como variável de merge, seja no texto do template ou em qualquer campo de texto dinâmico.
O resultado prático:
- Zero chamadas DML durante o envio dos e-mails
- Sem risco de estouro de limites independente do volume de destinatários
- Flow mais simples, mais rápido e mais fácil de manter
- Token disponível para qualquer outra automação que precise dele no futuro
Sobre o texto invisível no corpo do e-mail
A discussão original mencionou a tática de embutir o token no corpo do e-mail usando texto com cor branca ou letras minúsculas, um truque herdado da era dos Classic Email Templates para esconder o Ref ID do cliente final.
Antes de adotar essa abordagem, considere os riscos reais:
- Clientes de e-mail modernos, especialmente no modo noturno ,invertem esquemas de cor. Texto branco sobre fundo branco vira texto preto sobre fundo escuro. O token aparece.
- Algumas plataformas de e-mail reformatam o HTML antes da entrega, quebrando completamente o efeito de ocultação.
- A recomendação primária da Salesforce é confiar no rastreamento por cabeçalho nativo, que não toca no corpo da mensagem e não expõe string alguma ao cliente.
Se a exigência de negócio for inegociável e o token precisar estar no corpo, a abordagem do campo personalizado resolve o problema técnico de geração. Mas a decisão de inserir o token no corpo versus confiar nos cabeçalhos é uma conversa de requisito que precisa acontecer antes da implementação — não depois do primeiro bug relatado pelo cliente.
A lição arquitetural que fica
Esse cenário ilustra um padrão de erro muito comum em implementações Salesforce: forçar a plataforma a executar operações custosas no exato momento do disparo de uma automação voltada para o usuário final.
Soluções escaláveis funcionam ao contrário. Elas preparam o dado com antecedência — de forma assíncrona e desacoplada — para que a automação de interface seja o mais leve, segura e resiliente possível. Quando o Flow roda, ele apenas lê. Quem escreveu foi outro processo, em outro momento, dentro dos limites corretos.
Simples assim. E é exatamente essa simplicidade que diferencia uma arquitetura que aguenta crescimento de uma que quebra na primeira campanha com volume fora do padrão.
Em implementações de Service Cloud, lidar com Email-to-Case e rastreamento de threads é rotina. Colocar Apex invocável dentro de loops de Flow para gerar esses tokens é um atalho perigoso que consome limites DML silenciosamente. Entender como usar processos assíncronos para armazenar esses valores protege a org de falhas e garante escalabilidade.
A discussão reforça a transição do antigo Ref ID para o novo modelo de Threading Tokens da Salesforce, destacando armadilhas ocultas de DML em métodos nativos de e-mail.
- Crie o campo de armazenamento no objeto Case:
- Adicione um campo de texto personalizado no objeto Case — sugestão de nome:
Thread_Token__c. - Este campo será a fonte de verdade do token para todos os processos downstream, incluindo Flows e templates de e-mail.
- Implemente uma classe Queueable Apex para geração assíncrona do token:
- A classe deve receber o
Iddo Case como parâmetro e chamarEmailMessages.getFormattedThreadingToken(caseId)dentro do métodoexecute(). - Após obter o token, grave o valor no campo
Thread_Token__cvia DML — fora do contexto do loop ou do trigger original. - Use
System.enqueueJob()para disparar a classe a partir de um trigger after insert no Case, garantindo que a geração do token ocorra em uma transação separada.
- Ajuste o Flow para consumir o campo — não chamar Apex diretamente:
- Substitua qualquer chamada ao Apex invocável de geração de token dentro do Flow por uma referência direta ao campo
Thread_Token__c. - Se o Flow for acionado logo após a criação do Case, adicione um elemento de espera (Wait/Pause) ou valide se o campo já está preenchido antes de usá-lo — o Queueable pode não ter finalizado ainda.
- Valide os limites da transação antes de ir para produção:
- Teste cenários de criação em massa (mínimo 200 registros) para confirmar que nenhuma chamada ao
getFormattedThreadingToken()está ocorrendo dentro de loop ou contexto síncrono. - Monitore via Debug Logs e Apex Jobs se os Queueables estão sendo enfileirados e concluídos sem erros de limite.
- Documente a dependência arquitetural:
- Registre explicitamente que o campo
Thread_Token__cé populado de forma assíncrona e que qualquer automação dependente dele deve tratar o estado de campo vazio como válido durante a janela de processamento.
Evite usar a tática de texto invisível se puder. Clientes de e-mail com Dark Mode ativado frequentemente invertem as cores e expõem textos brancos ocultos. Prefira confiar no rastreamento via Email Headers sempre que possível.
Este conteúdo foi reescrito e analisado editorialmente em português a partir de informações públicas da fonte indicada.