Radar
Arquitetura// Curadoria editorial
Relevância
75
média

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.

Curadoria e análise de Guilherme Dornelas30 de junho de 20263 min de leitura
// Compartilhar
Gerar Thread IDs em loops no Flow destrói os limites DML do Email-to-Case

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:

  1. 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.
  2. 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.

// Por que isso importa

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.

// Minha leitura

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.

// Como aplicar na prática
  1. 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.
  1. Implemente uma classe Queueable Apex para geração assíncrona do token:
  • A classe deve receber o Id do Case como parâmetro e chamar EmailMessages.getFormattedThreadingToken(caseId) dentro do método execute().
  • Após obter o token, grave o valor no campo Thread_Token__c via 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.
  1. 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.
  1. 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.
  1. 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.
// Pontos de atenção

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.

Fonte original:Salesforce Stack Exchange — Flow

Este conteúdo foi reescrito e analisado editorialmente em português a partir de informações públicas da fonte indicada.

// Radar Salesforce — Newsletter

Releases, Flow, Revenue Cloud e Agentforce — com leitura de arquiteto, direto no seu e-mail.

Curadoria editorial em PT-BR, sem repost de notícia. Você recebe contexto, “por que importa” e como aplicar — assinada por mim.

Sem spam. Cancele quando quiser, em 1 clique.

// Sem spam · cancele quando quiser