Embudos y disparadores
Un embudo es un grafo. Una ejecución es una fila. Una espera es un tiempo.
Ese es el modelo completo, y cada propiedad difícil de este producto sale de esas tres frases. Editar un embudo en vivo es seguro gracias a ellas. Un reintento no puede enviar por duplicado gracias a ellas. Una persona que se da de baja el martes no recibe nada el jueves gracias a ellas.
Qué ocurre realmente cuando se ejecuta
Publicar un embudo escribe una versión inmutable. Alguien entra, y aparece una fila: una ejecución, para este contacto, fijada a esa versión, que contiene el nodo actual, una hora de despertar y su propio contexto.
Un worker arrienda las ejecuciones cuya hora de despertar ya pasó, reclamándolas con SKIP LOCKED para que dos workers no puedan tomar la misma. Ejecuta nodos hasta llegar a una espera o a un terminal, luego escribe la próxima hora de despertar y suelta.
Un nodo es una función pura de la ejecución, el contacto y el nodo — y sus efectos se confirman en la misma transacción que el propio avance de la ejecución. Esa única propiedad es lo que hace seguro un reintento. Un worker eliminado en el medio segundo entre «enviar» y «avanzar» deja ambos o ninguno, nunca uno.
Y como la aplicación suministra la hora en lugar de la base de datos, una fila escrita ahora vence ahora. Una columna de programación que usa por defecto el reloj de la base de datos aún no está vencida en el instante en que se escribe, y pierde el mismo tick que la creó — un error que no parece nada en absoluto hasta que un mensaje llega una hora tarde.
- 1Arrendar
wake_at <= now(),FOR UPDATE SKIP LOCKED. Una cola sin arrendamientos envía por duplicado por defecto. - 2EjecutarNodos en orden hasta una espera o un terminal. Cada uno escribe un paso: qué decidió, qué emitió.
- 3ConfirmarEfectos y avance, una transacción. Este es todo el truco.
- 4ReposoSe escribe el próximo
wake_at. Aún no existen filas posteriores, y no hace falta que exista ninguna.
Una ejecución por contacto por versión
Catorce disparadores
Qué puede iniciar una ejecución
Algunas de estas son cosas que tú haces. La mayoría son cosas que tu cliente hace, o no hace — y la ausencia de una acción es un disparador tan bueno como la acción misma.
Llegan
form_submit, list_join, contact_created, tag_added y segment_enter. Un segmento es un predicado en vivo, así que «entra en el segmento» cubre cada «se ha convertido en» que puedas expresar — tres pedidos, noventa días en silencio, gasta más de un umbral.
Hacen algo
page_visit desde el fragmento del sitio, message_opened, link_clicked, booking_made y payment_made. Que se abra un mensaje es en sí un evento en el contacto, así que un embudo puede esperar una reacción a lo último que envió.
El tiempo, o tú
date_field con un desfase — un cumpleaños, una renovación, «un año desde», siete días antes o tres días después. schedule para el recurrente. manual para el anuncio que envías porque decidiste hacerlo.
Tu propia aplicación
api_event es un evento personalizado que publicas desde tu propio código con tu propio token. Cualquier cosa que tu producto sepa se convierte en un disparador: activado, invitó a un colega, alcanzó el límite, canceló, exportó. Este es el que convierte una herramienta de correo en parte de tu producto.
Reentrada, decidida una vez
Un embudo es reentrante o no lo es, y la base de datos lo hace cumplir: una ejecución por contacto por embudo a menos que hayas dicho otra cosa. El mismo disparador activándose dos veces en el mismo segundo no puede producir dos ejecuciones por accidente.
Condiciones de entrada
Un disparador se activa y la especificación de entrada decide si este contacto en particular es elegible — un predicado de segmento frente a la puerta. Más barato que un nodo de condición en el primer paso, y mantiene el grafo centrado en lo que ocurre en lugar de en quién tiene permitido entrar.

Catorce cosas pueden iniciarlo. Dieciséis cosas pueden ocurrir después.
Dieciséis acciones y siete nodos de flujo
Qué puede hacer un embudo, y cómo decide
Enviar algo
send_email, send_sms, send_push, send_letter — cuatro canales, un grafo — más notify_team cuando la persona a la que hay que avisar trabaja para ti.
Modificar el contacto
add_tag, remove_tag, add_to_list, remove_from_list, set_field. Marcar a alguien sobre la marcha es lo que hace simple el segmento del próximo embudo.
Llegar hacia afuera
http_request a lo que quieras, create_payment contra tu propia cuenta conectada, y book_slot contra un recurso de reservas. El pagador sigue siendo tuyo; nadie se convierte en nuestro cliente.
Moverse entre embudos
enter_funnel y exit_funnel. Crea una secuencia de bienvenida y llámala desde cuatro sitios, en lugar de mantener cuatro copias que divergen para marzo.
Generar en el momento del envío
ai_generate rellena las variables de fusión por contacto, con medición contra tu cuota y caché por hash de creatividad y atributos del contacto — o pagarías por destinatario en cada envío.
Esperar, ramificar, dividir, unir
wait acepta una duración, una fecha y hora, un día de la semana con hora, o un campo de fecha con un desfase. condition es un predicado de segmento con un sí y un no. split es A/B/n con pesos. join vuelve a unir las ramas.
goal — el que importa
Un objetivo termina la ejecución para cualquiera que lo alcance. Reservaron, compraron, respondieron: el resto de la secuencia se cancela específicamente para ellos. Nadie recibe un «te echamos de menos» el día después de volver, y este es el nodo que lo evita.
throttle y quiet_hours
Throttle dosifica un picos de envío para que un buzón con un límite de tasa bajo no se sature hasta la suspensión. Las horas de silencio retienen un mensaje hasta una hora razonable — se aplican en la capa de mensaje, no se copian en cada rama del grafo.
Comprobado antes de poder ejecutarse
El validador te rechaza lo mismo a ti que a la IA
Un grafo se comprueba antes de poder publicarse, y la comprobación no es orientativa. Es la misma ruta de código tanto si una persona dibujó el embudo como si lo generó un modelo, que es la única razón por la que los embudos generados son fiables.
Exactamente una entrada
Dos nodos de entrada son una ambigüedad que nadie nota hasta que la mitad equivocada de una lista recibe la secuencia equivocada.
Todos los nodos alcanzables
Una rama huérfana es o bien un error o bien un mensaje que crees que se envía y no se envía. Ambos merecen que te avisen.
Todo ciclo debe contener una espera
Un bucle sin espera dentro es un bucle infinito con un envío en medio. Esta regla es la diferencia entre un embudo y un incidente.
Cada envío tiene su creatividad
Un nodo send_email sin creatividad ni asunto no puede publicarse. El mensaje con el asunto correcto y el cuerpo vacío es un modo de fallo real; se rechaza aquí.
Toda variable es conocida
Las variables de fusión se validan al publicar. {{frist_name}} es una errata que ves mientras editas, no un «Hola ,» llegando a cuarenta mil bandejas de entrada.
Luego simúlalo
Ejecuta una prueba en seco de un contacto real por todo el grafo y lee la ruta seguida y cada mensaje que se enviaría, con su día. Nada sale del edificio.
Los casos incómodos
Siete cosas que rompen un motor ingenuo
Cada una de estas es una prueba con un reloj determinista detrás, porque cada una rompe una implementación que parece perfectamente correcta hasta que se encuentra con la realidad.
- 1Un embudo que se repite en bucle sobre sí mismoLegítimo, común y correcto — siempre que el ciclo contenga una espera, cosa que el validador exige.
- 2Alguien se da de baja a mitad de caminoLa supresión se comprueba en el envío, no al encolar. Comprobar al encolar envía correo a quienes se fueron durante la espera.
- 3El embudo se edita con diez mil personas dentroSiguen recorriendo la versión con la que entraron, hasta el final. Los nuevos entrantes recorren la nueva.
- 4El mismo disparador se activa dos veces en un segundoUna sola ejecución, porque la unicidad es un índice en lugar de una comprobación seguida de una inserción.
- 5Un contacto se elimina a mitad de ejecuciónLa ejecución termina. Un borrado que deja una secuencia todavía dirigida a alguien no es un borrado.
- 6Una espera abarca un cambio de horario de verano"Tres días a las nueve de la mañana" significa las nueve de la mañana en ambos lados del cambio de hora.
- 7Un worker muere entre el envío y el avanceLos efectos y el avance son una sola transacción. O ocurrieron ambos o no ocurrió ninguno.
Reloj deterministaCada prueba rompe una implementación plausible
Las campañas son la otra mitad
Un funnel reacciona. Una campaign es el envío único de difusión: una audiencia, un calendario, un límite de envío y un envío. Es una cosa de otra forma y se mantiene deliberadamente separada en lugar de fingir que es un funnel con un solo nodo.
Dos reglas lo hacen seguro. Una audiencia se materializa una vez y se niega a ejecutarse dos veces — volver a resolverla añadiría silenciosamente a todos los que se unieron desde que empezó el envío, y el índice de deduplicación lo ocultaría al impedir los duplicados que ella misma creó. Y los contadores se recalculan a partir de los eventos de entrega, nunca se incrementan en el sitio, así que un webhook reintentado no puede inflar un informe.
Qué usar: si ocurre por algo que hizo la persona, es un funnel. Si ocurre por algo que decidiste un martes, es una campaign. Una cantidad sorprendente de automatización de marketing sale mal al forzar lo segundo en la forma de lo primero.