La respuesta breve
La pregunta "Flow o Apex" recibe una respuesta errónea cuando se evalúa en función de la facilidad de escritura o la disponibilidad del desarrollador. La respuesta correcta depende de cuatro factores técnicos: cuántos registros pasan en una sola transacción, si la lógica debe tener atomicidad completa, cuán complejas son las condiciones y las ramificaciones, y quién mantendrá el componente dentro de un año. Flow es la opción predeterminada correcta para la mayoría de las automatizaciones de negocio, pero existen puntos de inflexión claros en los que continuar trabajando con Flow crea un riesgo operativo y no solo un "código menos elegante".
Este artículo se centra en la decisión de elección misma: cómo identificar de antemano que la lógica justifica Apex, y cómo evitar una situación en la que la elección se hace por defecto y no por un juicio. La cuestión de la limpieza de Flows y procesos de automatización existentes que ya se han acumulado como deuda técnica se discute en un artículo separado y no forma parte de esta discusión.
Qué diferencia en la práctica a ambos a nivel de plataforma
Flow es un motor declarativo que se traduce en tiempo de ejecución a instrucciones que ejecutan DML y SOQL en nombre del usuario, mientras que Apex es un código compilado que se ejecuta bajo los mismos Governor Limits pero con control directo sobre el orden de las operaciones. La primera diferencia práctica es la "bulkificación": un desarrollador de Apex construye explícitamente un bucle que recopila todos los registros en una sola matriz y ejecuta un DML único, mientras que en Flow es fácil construir un bucle que realiza una operación DML o una consulta en cada iteración por separado, un patrón que alcanza el límite de 101 consultas permitidas mucho más rápido.
La segunda diferencia es el control de la transacción. Apex permite Savepoint y Database.rollback para una reversión parcial, manejo de DmlException a nivel de registro individual a través de Database.insert(list, false), y lógica condicional compleja sin límite de profundidad de ramificaciones. En Flow, el manejo de errores se define a nivel de "Fault Path" para cada elemento, y esto funciona bien para escenarios lineales pero se vuelve difícil de seguir cuando hay más de unas pocas rutas de fallo paralelas.
Marco de decisión: Cuatro pruebas antes de elegir una herramienta
Prueba de volumen
Regla general: Si el proceso se ejecuta en un solo registro como resultado de una acción del usuario (creación de un lead, cambio de estado de una oportunidad), Flow es casi siempre suficiente. Si el proceso se ejecuta en decenas o miles de registros a la vez —actualización periódica, procesamiento por lotes que proviene de una integración, limpieza de datos programada— Apex con Batchable o Queueable es la elección segura, ya que otorga control total sobre la "bulkificación" y la gestión de Governor Limits frente a un volumen cambiante.
Prueba de atomicidad
Debemos preguntar: Si parte de la actualización falla, ¿se permite que la otra parte permanezca guardada? Si la respuesta es "no" —por ejemplo, la actualización de un pedido y la creación de un registro de facturación que deben ocurrir juntas— Apex con Savepoint es la forma correcta de garantizarlo. Flow no proporciona una reversión completa entre elementos sin una construcción manual y compleja de lógica de compensación.
Prueba de complejidad de ramificaciones
Un Flow con más de 6-8 elementos Decision anidados se vuelve difícil de leer y costoso de probar, incluso si cada ramificación individual es simple. Cuando la complejidad de la lógica de negocio excede esto, escribir la misma lógica como una función Apex documentada con pruebas unitarias (@isTest) suele ser más económico de mantener, incluso si el tiempo de escritura inicial es mayor.
Prueba de mantenimiento y propiedad
Debemos preguntar quién mantendrá el componente dentro de un año, no quién lo construye ahora. Si es el equipo de Admin quien tendrá que actualizar las reglas de negocio de forma rutinaria —como cambiar las condiciones de descuento o los umbrales— Flow es preferible incluso si Apex es técnicamente "más limpio", porque es accesible para actualizar sin un ciclo de implementación. Si los cambios requieren conocimiento del esquema de datos y pruebas de regresión, Apex es la elección correcta incluso si solo hay un pequeño equipo de desarrollo que lo mantendrá.
Tabla de decisión
| Criterio | Elegir Flow | Elegir Apex |
|---|---|---|
| Volumen de registros en una sola transacción | Hasta unas pocas decenas | Cientos a miles |
| Requisito de atomicidad entre varios objetos | No crítico | Crítico — se requiere reversión completa |
| Número de ramas de decisión | Hasta 6-8 aproximadamente | Más de esto, o lógica recursiva |
| Frecuencia de cambio de las reglas de negocio | Frecuente, por Admin | Rara, requiere pruebas de regresión |
| Necesidad de llamar a una API externa compleja | Llamada única sencilla (HTTP Callout) | Lógica de reintento, autenticación compleja o por lotes |
| Requisito de pruebas automáticas (CI) | Limitado | Completo, @isTest con Coverage |
| Integración con un trabajo programado fijo | No es directamente adecuado | Natural a través de Schedulable |
Escenario de ejemplo: Empresa de equipos médicos con proceso de aprobación de pedidos
Una empresa de equipos médicos mediana con aproximadamente 40 representantes de ventas implementó un Flow para el proceso de aprobación de pedidos: verificación de inventario, cálculo de descuento, creación de un registro de aprobación y envío de una notificación al gerente. Al principio, funcionó bien para pedidos individuales. Después de seis meses, se añadió un nuevo escenario: la importación de pedidos por lotes desde un archivo de integración con el ERP, que creaba entre 200 y 800 pedidos simultáneamente.
El Flow, que se activaba a través de un Record-Triggered Flow a nivel "por registro", realizaba una consulta de verificación de inventario dentro de cada ejecución por separado. Con la importación de 500 pedidos, el sistema superó el límite de 100 consultas en una sola transacción y los pedidos fallaron sin un mensaje de error claro para el usuario. El equipo identificó que el problema no estaba en el Flow en sí, sino en la adaptación entre un proceso diseñado para un solo registro y un escenario de volumen que no existía en el momento de la construcción.
La solución no fue descartar el Flow. El equipo dividió la lógica: Flow se mantuvo responsable del proceso manual de un solo pedido (la prueba de volumen era baja, era necesario que el Admin actualizara frecuentemente las reglas de descuento), mientras que el proceso de importación por lotes se transfirió a un Apex Batch Job que realiza una "bulkificación" completa, verifica el inventario en una única consulta centralizada y ejecuta un DML único para todos los registros. Ambos mecanismos llaman a la misma capa de lógica de negocio compartida (una Apex Class a la que también se accede desde el Flow a través de un Invocable Method), para que la regla de descuento no se mantenga dos veces.
Riesgos comunes y acciones preventivas
| Riesgo | Cómo se manifiesta en la práctica | Acción preventiva |
|---|---|---|
| Flow en un volumen que crece gradualmente | El proceso funcionó durante seis meses y luego falló silenciosamente debido a los Governor Limits | Evaluar el volumen esperado a un año y planificar un punto de transición a Apex antes de alcanzar el límite |
| Duplicidad de lógica de negocio en Flow y Apex | Dos lugares calculan el descuento de manera diferente | Centralizar el cálculo de negocio en una capa Apex compartida a la que también acceda Flow |
| Orden de Trigger inesperado | Varios Flows y Triggers en el mismo objeto entran en conflicto | Un único Trigger Handler central en Apex para cada objeto crítico |
| Manejo parcial de errores en Flows complejos | Parte de los registros se actualizan y parte no, sin visibilidad | Mover procesos que requieren atomicidad a Apex con Savepoint |
| Apex sin pruebas suficientes | Un pequeño cambio rompe un proceso crítico en la siguiente implementación | Exigir un Coverage real y no solo un porcentaje formal, incluyendo escenarios de fallo |
Lista de verificación para la decisión antes de construir
- ☐ Se ha verificado el volumen esperado a un año, no solo el estado actual.
- ☐ Se ha definido si el proceso requiere atomicidad entre varios objetos.
- ☐ Se ha contado el número esperado de ramas de decisión en la lógica.
- ☐ Se sabe quién mantendrá el componente y con qué frecuencia cambiarán las reglas.
- ☐ Se ha verificado si ya existe una lógica similar en Apex o en otro Flow en el mismo objeto.
- ☐ Se ha definido el
Trigger Ordersi hay varios mecanismos de automatización en el objeto. - ☐ Si se eligió Apex — se han definido escenarios de prueba, incluyendo fallos parciales.
- ☐ Si se eligió Flow — se ha definido un
Fault Pathpara cada elemento crítico.
Cómo se conecta esto con la arquitectura más amplia
La elección de la herramienta correcta para una automatización individual es solo una capa dentro de una imagen más amplia de la arquitectura de CRM, donde tanto el modelo de datos como los permisos afectan a lo que Flow o Apex pueden siquiera tocar. Cuando la automatización cruza una frontera hacia una organización externa, por ejemplo, la verificación de inventario contra un ERP en tiempo real, la elección entre Flow y Apex también se integra en las consideraciones de patrones de integración y en la cuestión de cómo Salesforce se conecta a un ERP en términos de latencia y manejo de fallos.
En organizaciones que operan varias organizaciones (orgs), también es necesario verificar si la lógica de negocio es idéntica en todas ellas, un tema que se discute en la guía de Single Org frente a Multi Org y que influye en la cuestión de si vale la pena centralizar la lógica en un Apex Package compartido.
Resumen
La elección entre Flow y Apex no es una cuestión de habilidad del equipo o preferencia personal, sino el resultado de cuatro pruebas técnicas: volumen, atomicidad, complejidad de las ramificaciones y frecuencia de cambio. Flow es la opción predeterminada correcta para la mayoría de las automatizaciones que afectan a un solo registro y cambian con frecuencia. Apex es necesario cuando hay un volumen significativo, cuando se necesita un control total sobre la transacción, o cuando la complejidad lógica supera un umbral que aún puede mantenerse a través de una interfaz declarativa. Una organización que institucionaliza estas pruebas como parte del proceso de trabajo —y no las deja al juicio ad-hoc de cada desarrollador— ahorra la mayoría de los casos en los que una automatización que funcionó bien al principio se rompe silenciosamente cuando el volumen aumenta.
