Categorías
Desarrollo en Salesforce

Salesforce » Rendimiento: Errores que todos cometen [Masterclass]

Un flow que anda con tres contactos puede tumbar la Org al crecer: entry conditions, Get Records, DML en loop, storage de 2 KB por registro y CPU time.

Un flow que pasa el debug no es un flow listo para producción. En esta masterclass de Discover, Josu, Desti y el equipo muestran cómo una automatización chica termina en CPU time exceeded cuando tu empresa crece.

El patrón se repite: Get Records de más, loop que actualiza y entry conditions flojas. Aplica a Flow y a Apex. Abajo está el video. Después, el mapa de límites, storage y cuándo ejecutar. Al final, preguntas frecuentes.

Play

Por qué un flow que anda tumba la Org cuando crece

La premisa de Josu fue chica a propósito. Una cuenta tiene un manager. Cuando cambia ese manager, todos los contactos de la cuenta deben pasar a su ownership. El requerimiento cabe en una frase y se siente urgente.

En la clase armamos un record-triggered flow sobre Account. Corre al actualizar, pide contactos relacionados, itera y actualiza el OwnerId. El debug con un registro funciona. Producción lo recibe. Meses después llega el CPU time.

Eso no es un bug de Salesforce. Es el costo de entregar valor ahora y dejar el después lo mejoro para nunca. Lo provisorio se queda. Código que anda no se toca, hasta que pincha.

El record-triggered flow: Get Records, loop y Update

Josu mostró el dibujo típico. Trigger sobre cuenta, Get Records de Contact donde AccountId es el triggering record, Loop, Assignment del owner y Update Records adentro del ciclo. Visualmente parece limpio.

El problema es aritmético. Si la cuenta tiene 80 contactos, ese Update adentro del loop son 80 DML. Cada DML dispara automatización de Contact. Si esos contactos tocan otros objetos, la transacción se rompe.

Los governor limits no perdonan: 150 sentencias DML y 10.000 filas DML por transacción. Cien consultas SOQL. 50.000 filas de query. Diez segundos de CPU síncrono. Un flow correcto con tres contactos no avisa.

Buena práctica: el Get y el Update viven fuera del loop. Adentro, solo Assignment a una collection. Una sola escritura masiva al final. Eso es bulkification, y vale igual en Apex: nunca SOQL ni DML dentro de un for.

  • Record-triggered flow sobre Account, after-save, registros relacionados.
  • Get Records de Contact filtrado por la cuenta que disparó el trigger.
  • Loop solo para asignar OwnerId a una collection variable.
  • Un Update Records masivo fuera del ciclo, nunca adentro.

Entry conditions de verdad

El segundo error es más silencioso. El flow corre cada vez que se actualiza la cuenta, no solo cuando cambia el manager. Le tocan el teléfono y igual hay Get, loop y DML. El usuario no ve nada. La Org sí: CPU invisible.

En el chat lo marcaron dos veces. Si el flow solo corre en update, un alta de cuenta no replica el manager. Y hace falta Set entry conditions cuando el campo relevante cambia. Las dos observaciones son el mismo principio: reducir el escenario.

Josu lo dijo claro. Vimos Orgs con 20, 30 y más de 300 flows sobre un solo objeto. Si cada uno corre por las dudas, en algún momento Salesforce corta con too many SOQL.

Los errores se apilan: too many DML statements, Apex CPU time limit exceeded. No hace falta que alguien despliegue código nuevo. Basta con que crezca el volumen de registros de tu empresa.

En Decision hay un check que casi nadie mira: ejecutar siempre que el registro cumpla, o solo cuando el registro cambió y empezó a cumplir. Cierras una oportunidad, mandas un mail y después editas la descripción: sale el segundo mail.

Eso se conecta con la masterclass de gestión de errores en Flow: un fallo por límite no es un mensaje rojo amable. Es una transacción que aborta y un usuario que no puede guardar.

Record types: filtrar antes de pensar

Desti trajo la experiencia de Business Units en la misma Org. Una Account para una unidad no es la misma Account para otra. Si el entry condition no filtra por record type, el flow de una unidad ejecuta la lógica ajena.

En el chat recordaron que en entry conditions puedes usar fórmula y RecordType.DeveloperName. No hace falta hardcodear el Id del tipo de registro. Un Decision más abajo también sirve, pero el filtro temprano ahorra Get Records.

Cuando tu empresa suma países, listas de precio y procesos, el record type deja de ser cosmética de layout. Es la primera compuerta de performance. Menos ejecuciones, menos CPU, menos sorpresas al agregar una unidad de negocio.

Get Records de más y las 50.000 filas

El Get de todos los contactos de la cuenta funciona hasta que no. El límite de filas SOQL por transacción es 50.000. Josu contó un caso real: una query de productos para armar pricebooks anduvo tres años. Un día, más de 50.000 productos.

La solución de quince minutos fue ponerle Limit 50.000. Eso no es diseño. Es tapar el síntoma. Lo que hay que preguntar es por qué esa query necesita el universo. Filtros, lotes, async: el Limit máximo es una trampa.

El mismo criterio aplica si tu empresa integra Salesforce con otro sistema. En la masterclass de integraciones sin código con Flow vimos que un Get gordo no solo tumba la transacción: satura el payload.

Salesforce como edificio: convivir con governor limits

En el chat llegó la pregunta clásica: en Salesforce todo es eterno y no hay límites, no es que la nube está en el cielo. Josu armó la analogía del edificio. Cada Org es un departamento. Compartes agua, ruido y horario con vecinos invisibles.

Salesforce pone límites para que todos convivan. Si tu automatización funciona pero no es óptima, el vecino no entra. A veces el bloqueo dura una hora, a veces 24 horas. Nuestra obligación es automatizar sin molestar a tu empresa ni a sus vecinos.

Esa convivencia es el modelo de la nube: recursos compartidos, no un servidor exclusivo. En EGA Futura construimos ERP nativo sobre esa misma infraestructura. El rendimiento de un flow no es un detalle de CRM: es la plataforma entera.

A veces ampliar el agua se paga. Storage extra, Big Objects, External Objects, Field History de 20 a 60 campos: Salesforce te vende techo. Antes de comprar, conviene leer precios con la misma lupa que usamos para un DML en loop.

  • 100 SOQL por transacción síncrona.
  • 50.000 filas recuperadas por SOQL.
  • 150 DML y 10.000 filas DML.
  • 10.000 ms de CPU síncrono (60.000 ms async).

IDs hardcodeados y lo provisorio que se queda

Desti insistió en otra deuda: IDs clavados en Flow. En Apex está más naturalizado que no se hace. En Flow se ve todo el tiempo. El registro se borra, el sandbox no replica el Id, y la automatización apunta al vacío.

Custom Metadata es el nivel pro de no hardcodear. En el chat lo dijeron así. Igual hay que gobernarlo: metadata mal usada es hardcodeo con traje. Nombres de variables d o a son la misma prisa. El después lo arreglo no llega.

Permisos de apuro y Field History

El apuro también abre de más. Campo Manager nuevo, permiso para todos, al layout, a producción. Pierdes el control de quién setea un límite de crédito. Eso es seguridad y es performance: más perfiles gordos, más superficie.

Francisco recordó Field History: hasta 20 campos nativos por objeto, con upgrade a 60. Útil para cuenta bancaria o crédito. Auditar que Juan pasó a Juancho llena storage.

La gobernanza de quién ve qué la profundizamos en la masterclass de seguridad y gobernanza. Mínimo privilegio también ahorra recálculos de sharing y bloqueos.

Storage: 2 KB por registro y el volumen que duele

Cada registro en Salesforce pesa 2 KB, tengas un campo o cincuenta. Una Org histórica tenía 1 GB. Hoy el piso típico ronda 10 GB: unos 5 millones de registros. No es infinito.

Crear objetos de join porque el modelo da puede ser un suicidio de storage. El registro vacío y el registro lleno pesan lo mismo. Esa es la regla que obliga a pensar el volumen.

Josu contó el caso de promociones. Un millón de cuentas, 20 promos, todas para todas. El join daba 20 millones de filas para mandar por API. Conceptualmente correcto. En Salesforce, inútil y caro.

La salida fue no crear la tabla. Niveles en cuenta y promo, y materializar el uso solo cuando importa. Cumplir el modelo relacional no es lo mismo que cuidar la Org.

Storage Usage muestra el peso por objeto. Hay quien guarda todos los EmailMessage por las dudas. Fotos de perfil que llenan file storage para ver la cara del cliente: mejor un bucket externo. Salesforce llama para vender disco. Nosotros preferimos menos registros.

Data vieja: archivar, consolidar, no borrar a ciegas

Borrar casos para liberar espacio y después restaurar dos años de historial es una anécdota que duele. El export nativo genera ZIPs con CSV. La papelera guarda unos 90 días.

Restaurar con Salesforce a veces sale más caro que re-subir: un mes de carga versus 20 minutos de delete. El manager pide el historial 2022-2024 y hay que inventar External ID para volver a cargar.

Antes de tocar data de producción, el pedido va por escrito. Si el negocio puede hacerlo con una herramienta, mejor. Si lo hacemos nosotros, nos cubrimos. No es poca voluntad: es no quemarse.

Desti armó el mapa de archivo. Big Objects: millones de filas, casi sin automatización, licencia. Base externa más job de export, y External Objects si quieres verlo en Salesforce: también se paga.

Francisco sumó objetos de consolidación: 15.000 oportunidades de un mes en un registro resumen. Doce filas por año por cuenta. La información sigue adentro, accesible, con una fracción del storage.

Esa práctica gobierna el tamaño porque cada registro pesa lo mismo. Hay aplicaciones en AppExchange que consolidan. La misma lógica aplica si tu empresa expone procesos en Experience Cloud: menos basura en la Org, menos CPU para comunidades.

Lo vimos al farmear Aura y LWC en la masterclass multi-framework de Experience Cloud. Una comunidad lenta casi siempre es una Org pesada, no un tema de framework.

CPU time, Log Analyzer y Scale Center

El límite que más miedo le da a Josu es Apex CPU time. Cuando la Org ya tiene flows, triggers y deuda, el Log Analyzer de Visual Studio Code baja el log y arma el call stack.

La herramienta marca SOQL, filas y CPU por método, y pinta en rojo dónde pinchó. Sirve cuando heredamos automatización vieja y no tenemos el mapa completo de la transacción.

Scale Center es la foto de salud de la Org. No es un botón en todas partes: hay que hablar con un representante para habilitarlo. Sirve para dejar de discutir que Salesforce anda lento.

Mides el pico de las 15:00, el batch de mails, los segundos de crear una oportunidad. Deja de ser una sensación y pasa a ser un número.

Coverage de tests y Application son otra vista de la misma higiene. Un flow lento y un trigger lento compiten en la misma transacción. Por eso esta clase aplica a Flow y a Apex.

Las herramientas de vibe coding no te eximen. Hay que reglamentar el desarrollo, no solo el canvas. Un Get adentro de un loop generado por un modelo es el mismo error de siempre, con otra firma.

Cómo analizar, probar y decidir cuándo ejecutar

Probar con un registro en debug es necesario y es mentira. El lote interno de Salesforce ronda 200 registros. Si no pruebas un Data Loader de 200 cuentas con 40 contactos cada una, no viste el flow.

Lo que anda en sandbox chico pincha en producción grande. El volumen de tu empresa no es un detalle de UAT: es el escenario real de los governor limits.

La pregunta de diseño no es si puedo hacerlo. Es para qué, con qué volumen, en qué momento. Before-save si tocas el mismo registro. After-save si tocas relacionados. Async si no tiene que vivir en el clic del usuario.

Entry condition específica. Record type adelante. DML afuera. Tres reglas que evitan el 80 por ciento de las caídas que vimos en la clase.

En EGA Futura estamos armando una guía de estándares de desarrollo: Flow y Apex juntos, nomenclatura de nodos, no meter DML en for, para dársela también a Cursor. El mérito de arrancar ese documento es de Fran.

Son 38 páginas que Salesforce no publica así. Próximamente, acceso para proyectos. Mientras tanto, el calendario de clases está en Salesforce con EGA Futura: un jueves masterclass, el otro inglés para Salesforce.

Si tu empresa vive en la misma Org el CRM y el ERP, este cuidado de límites no es opcional: es continuidad.

La mirada de EGA Futura sobre rendimiento

En EGA Futura construimos ERP nativo potenciado por Salesforce. Las aplicaciones conviven con tus flows. Un loop mal puesto no rompe solo el CRM: rompe stock, facturación y el clic del usuario.

Por eso publicamos la solución en el AppExchange de Salesforce. Plataforma única exige la misma disciplina de límites en CRM y en operación.

Agenda una demo. Dura 30 a 45 minutos, es sin compromiso y la da una persona del equipo. Puedes ver precios, recorrer las aplicaciones o empezar por egafutura.com.

Empieza por medir los flows que corren siempre, no por comprar más storage.

Preguntas frecuentes sobre rendimiento en Salesforce

Respuestas cortas a lo que más se repite después de la masterclass: entry conditions, DML en loop, storage, CPU y Scale Center. Sirve como mapa rápido para admins y developers de empresas medianas.

Un record-triggered flow que pasa el debug está listo para producción?

No. El debug con un registro no ejercita governor limits. Prueba lotes reales, entry conditions y el camino de relacionados. Un flow que anda con tres contactos puede tumbar la Org con trescientos.

Dónde van Get Records y Update en un loop de contactos?

Afuera. Adentro solo Assignment a una collection. Un Update por iteración dispara DML y toda la automatización de Contact. La misma regla vale en Apex: nada de SOQL ni DML dentro del for.

Qué entry condition conviene en un flow de Account?

La más chica que cumpla el negocio. En el ejemplo, cuando cambia el manager, más record type si hay Business Units. Evita cada vez que se actualiza la cuenta. En Decision, usa solo cuando el registro empieza a cumplir.

Cuánto pesa un registro y cuándo duele el storage?

Unos 2 KB por registro, casi da igual la cantidad de campos. 10 GB ronda 5 millones de filas. Joins todos-con-todos, mails eternos y fotos de perfil llenan la Org. Archiva, consolida o externaliza antes de pagar más disco.

Scale Center y Log Analyzer reemplazan diseño?

No. Log Analyzer te dice dónde pinchó el CPU. Scale Center mide si la Org está lenta en un pico. Ninguno perdona un Get de 50.000 filas ni un DML en loop. Primero diseño, después telemetría.

Esto aplica solo a Flow?

No. Josu y Desti lo marcaron de entrada: las mismas precauciones de Flow valen en Apex. Vibe coding incluido. Límites por transacción, bulkification y entry conditions son de plataforma, no de canvas.

Por Juan Manuel Garrido

Fundador de EGA Futura, empresa que desde 1994 desarrolla software de gestión empresarial. Creó el ERP nativo para Salesforce, que elimina los problemas de sincronización, falta de visibilidad y doble administración que aparecen al integrar un ERP externo con el CRM, y EGA Futura ERP en la nube para empresas medianas que todavía dependen de sistemas rígidos. Es cofundador de Vantegrate, nacida en 2024 de la fusión entre Ventix Solutions y EGA Futura, que desarrolla una suite de agentes de inteligencia artificial llave en mano para empresas medianas y grandes de Latinoamérica. Escribe sobre gestión empresarial, la plataforma Salesforce y estrategia comercial.