Funis & gatilhos
Um funil é um grafo. Uma execução é uma linha. Uma espera é um tempo.
Esse é o modelo inteiro, e todas as propriedades difíceis deste produto saem dessas três frases. Editar um funil em produção é seguro por causa delas. Uma repetição não pode enviar em duplicado por causa delas. Quem cancela a subscrição na terça-feira não ouve nada na quinta-feira por causa delas.
O que acontece realmente quando corre
Publicar um funil escreve uma versão imutável. Alguém entra, e aparece uma linha: uma execução, para este contacto, fixada a essa versão, guardando o nó atual, uma hora de despertar e o seu próprio contexto.
Um worker arrenda as execuções cuja hora de despertar já passou, reclamando-as com SKIP LOCKED para que dois workers não possam pegar na mesma. Executa nós até chegar a uma espera ou a um terminal, depois escreve a próxima hora de despertar e solta.
Um nó é uma função pura da execução, do contacto e do nó — e os seus efeitos são confirmados na mesma transação que o avanço da própria execução. Essa única propriedade é o que torna uma repetição segura. Um worker morto no meio segundo entre "enviar" e "avançar" deixa ou ambos ou nenhum, nunca um.
E como a aplicação fornece a hora em vez da base de dados, uma linha escrita agora vence agora. Uma coluna de agendamento com valor por omissão do relógio da base de dados ainda não está vencida no instante em que é escrita, e perde o próprio tique que a criou — um bug que não parece nada até uma mensagem chegar uma hora atrasada.
- 1Arrendar
wake_at <= now(),FOR UPDATE SKIP LOCKED. Uma fila sem arrendamentos envia em duplicado por omissão. - 2ExecutarNós por ordem até uma espera ou um terminal. Cada um escreve um passo: o que decidiu, o que emitiu.
- 3CommitEfeitos e avanço, numa transação. Este é todo o truque.
- 4SuspenderPróximo
wake_atescrito. Ainda não existem linhas a jusante, e nenhuma precisa de existir.
Uma execução por contacto por versão
Catorze gatilhos
O que pode iniciar uma execução
Alguns destes são coisas que tu fazes. A maioria são coisas que o teu cliente faz, ou não faz — e a ausência de uma ação é tão bom gatilho como a própria ação.
Eles chegam
form_submit, list_join, contact_created, tag_added e segment_enter. Um segmento é um predicado em tempo real, por isso "entra no segmento" cobre todos os "tornou-se" que consigas exprimir — três encomendas, noventa dias em silêncio, gasta acima de um limiar.
Eles fazem algo
page_visit a partir do snippet do site, message_opened, link_clicked, booking_made e payment_made. Uma mensagem aberta é em si um evento no contacto, por isso um funil pode esperar pela reação à última coisa que enviou.
O tempo, ou tu
date_field com um deslocamento — um aniversário, uma renovação, "um ano desde", sete dias antes ou três dias depois. schedule para o recorrente. manual para o anúncio que envias porque decidiste.
A tua própria aplicação
api_event é um evento personalizado que publicas a partir do teu próprio código com o teu próprio token. Tudo o que o teu produto sabe torna-se um gatilho: ativado, convidou um colega, atingiu o limite, cancelou, exportou. Este é o que transforma uma ferramenta de mailing em parte do teu produto.
Reentrada, decidida uma vez
Um funil é reentrante ou não é, e a base de dados impõe-no: uma execução por contacto por funil, a menos que digas o contrário. O mesmo gatilho a disparar duas vezes no mesmo segundo não pode produzir duas execuções por acidente.
Condições de entrada
Um gatilho dispara e a especificação de entrada decide se este contacto em particular é elegível — um predicado de segmento à porta da frente. Mais barato do que um nó de condição no primeiro passo, e mantém o grafo focado no que acontece em vez de em quem tem permissão para entrar.

Catorze coisas podem iniciá-lo. Dezasseis coisas podem acontecer a seguir.
Dezasseis ações e sete nós de fluxo
O que um funil pode fazer, e como decide
Enviar algo
send_email, send_sms, send_push, send_letter — quatro canais, um grafo — mais notify_team quando quem precisa de saber trabalha contigo.
Alterar o contacto
add_tag, remove_tag, add_to_list, remove_from_list, set_field. Marcar alguém ao longo do caminho é o que torna o segmento do próximo funil simples.
Alcançar o exterior
http_request para o que quiseres, create_payment contra a tua própria conta conectada, e book_slot contra um recurso de reservas. O pagador continua a ser teu; ninguém se torna nosso cliente.
Mover entre funis
enter_funnel e exit_funnel. Cria uma sequência de boas-vindas e chama-a de quatro lugares, em vez de manter quatro cópias que divergem até março.
Gerar no momento do envio
ai_generate preenche as variáveis de mesclagem por contacto, contabilizado contra a tua quota e em cache por hash de criativo e de atributo do contacto — senão pagarias por destinatário em cada envio.
Esperar, ramificar, dividir, juntar
wait aceita uma duração, uma data e hora, um dia da semana com hora, ou um campo de data com um desvio. condition é um predicado de segmento com um sim e um não. split é A/B/n com pesos. join volta a unir as ramificações.
goal — o que realmente importa
Um objetivo termina a execução para qualquer pessoa que o alcance. Marcou reunião, comprou, respondeu: o resto da sequência é cancelado especificamente para essa pessoa. Ninguém recebe "sentimos a tua falta" no dia seguinte a ter voltado, e este é o nó que o impede.
throttle e quiet_hours
O throttle controla o ritmo de uma rajada para que uma caixa de correio com um limite baixo de taxa não seja martelada até à suspensão. As horas de silêncio retêm uma mensagem até uma hora civilizada — aplicadas ao nível da mensagem, não copiadas para cada ramo do grafo.
Verificado antes de poder executar
O validador recusa as mesmas coisas para ti e para a IA
Um grafo é verificado antes de poder ser publicado, e a verificação não é meramente consultiva. É o mesmo caminho de código quer uma pessoa tenha desenhado o funil quer um modelo o tenha gerado, o que é a única razão pela qual os funis gerados são minimamente fiáveis.
Exatamente uma entrada
Dois nós de entrada são uma ambiguidade que ninguém repara até que a metade errada de uma lista receba a sequência errada.
Todos os nós alcançáveis
Um ramo órfão é ou um erro ou uma mensagem que achas que vai ser enviada e não vai. Ambos valem a pena ser comunicados.
Um ciclo tem de conter um wait
Um loop sem wait é um loop infinito com um envio no meio. Esta regra é a diferença entre um funil e um incidente.
Cada envio tem o seu criativo
Um nó send_email sem criativo e sem assunto não pode ser publicado. A mensagem com o assunto certo e o corpo vazio é um modo de falha real; é recusado aqui.
Cada variável é conhecida
As variáveis de mesclagem são validadas na publicação. {{frist_name}} é um erro de digitação que vês enquanto editas, não um "Olá ," a chegar a quarenta mil caixas de entrada.
Depois simula-o
Faz um ensaio com um contacto real através de todo o grafo e lê o caminho percorrido e cada mensagem que seria enviada, com o seu dia. Nada sai do edifício.
Os casos incómodos
Sete coisas que partem um motor ingénuo
Cada uma delas é um teste com um relógio determinístico por trás, porque cada uma parte uma implementação que parece perfeitamente correta até encontrar a realidade.
- 1Um funil que faz loop sobre si mesmoLegítimo, comum e aceitável — desde que o ciclo contenha um wait, o que o validador exige.
- 2Alguém cancela a subscrição a meio do percursoA supressão é verificada no envio, não no enfileiramento. Verificar no enfileiramento envia correio para as pessoas que saíram durante a espera.
- 3O funil é editado com dez mil pessoas lá dentroContinuam a percorrer a versão em que entraram, até ao fim. Os novos entram na nova.
- 4O mesmo gatilho dispara duas vezes num segundoUma execução, porque a unicidade é um índice e não uma verificação seguida de um insert.
- 5Um contacto é apagado a meio da execuçãoA execução termina. Um apagamento que deixa uma sequência ainda endereçada a alguém não é um apagamento.
- 6Uma espera atravessa uma mudança de hora"Três dias às nove da manhã" significa nove da manhã nos dois lados da mudança de hora.
- 7Um worker é morto entre o envio e o avançoEfeitos e avanço são uma única transação. Ou ambos aconteceram ou nenhum aconteceu.
Relógio determinísticoCada teste quebra uma implementação plausível
As campanhas são a outra metade
Um funil reage. Uma campanha é a difusão pontual: uma audiência, um agendamento, um limitador e um envio. É uma coisa de outra forma e é deliberadamente mantida separada, em vez de fingir ser um funil com um só nó.
Duas regras tornam-na segura. Uma audiência é materializada uma vez e recusa-se a correr duas vezes — voltar a resolvê-la acrescentaria silenciosamente todos os que entraram desde o início do envio, e o índice de deduplicação esconderia isso ao impedir os duplicados que criou. E os contadores são recalculados a partir dos eventos de entrega, nunca incrementados no local, para que um webhook repetido não possa inflacionar um relatório.
Qual usar: se acontece por causa de algo que a pessoa fez, é um funil. Se acontece por causa de algo que decidiste numa terça-feira, é uma campanha. Uma quantidade surpreendente de automação de marketing corre mal por forçar a segunda para a forma da primeira.