Colas y procesos en segundo plano: cuándo tu web los necesita

Enviar un mail o generar un PDF en la petición HTTP es una bomba de tiempo. Jobs, reintentos y cuándo extraer el trabajo pesado.

El usuario pulsa «Confirmar». La petición HTTP genera el PDF, habla con el SMTP, espera al proveedor de pago y, si hay suerte, responde en cuatro segundos. Si el SMTP se atasca, la página se queda en blanco y el pedido ha podido cobrarse. Las colas jobs segundo plano no son moda de arquitectura: son dejar de poner una bomba en el request.

No toda web lo necesita. Un corporativo que manda un formulario a un correo y ya, a menudo no. Una plataforma que emite entradas, genera documentos, sincroniza stock o dispara emails transaccionales en cada compra, sí. La pregunta no es «¿tenemos Redis?». Es qué trabajo no puede permitirse fallar en la cara del usuario.

Este artículo marca cuándo extraer el trabajo pesado en un desarrollo web a medida, qué implica reintentar, y qué no hace falta convertir en microservicio. El criterio que usamos en Truman cuando el monolito todavía aguanta —y cuando el request ya no.

El request espera al mundo exterior
Mail, PDF, API de terceros, thumbnails. Si uno de ellos tarda, la petición entera tarda. Si uno falla, el usuario ve un 500.
El fallo no se puede repetir
El cobro pasó. El mail no. Nadie reintenta. El soporte se entera por el cliente, no por un job fallido.
El pico tumba el PHP
Un envío masivo o un cierre de ventas llena los workers de Apache o de PHP-FPM haciendo trabajo que no debería estar en el front.

Colas jobs segundo plano: qué problema resuelven de verdad

Una cola no es «más moderno». Es un sitio donde dejas un trabajo para que otro proceso lo haga después: enviar el correo, generar el PDF, llamar a un webhook, redimensionar una imagen, cerrar un lote. El request HTTP se limita a validar, persistir lo esencial y responder. El usuario no espera al SMTP.

Eso cambia tres cosas. Latencia: la página responde en el tiempo de tu base de datos, no en el del proveedor más lento. Resiliencia: si el mailer cae, el job queda y se reintenta. Capacidad: el pico de trabajo pesado no se come los procesos que sirven HTML. Sin eso, cada «mejora» de producto (un PDF más, un segundo email, un OCR) alarga el request hasta que un día revienta.

No sustituye a un buen hosting y caché. Una cola no arregla un TTFB malo ni un shared saturado. Extrae trabajo. Si el trabajo que sirve la página es el que está lento, el problema es otro.

Lo que no debería vivir en la petición HTTP

Hay una lista corta y aburrida. Si tu web hace dos o más de estas cosas dentro del controller, ya estás en zona de riesgo —aunque hoy el tráfico sea bajo.

Trabajo¿En el request?Por qué
Validar y guardar el pedido o el leadSíEs el resultado que el usuario necesita ver ahora
Email transaccional (confirmación, entrada)ColaEl SMTP falla. El usuario no tiene que esperar
PDF, entradas, facturas, zipsColaCPU y tiempo. Un timeout deja el cobro a medias
Llamadas a APIs lentas o inestablesCola o asíncronoRate limits, caídas, 30 segundos de cortesía
Thumbnails, transcodificación, importsColaNo son una respuesta de página. Son un proceso
Un formulario que solo manda un correoA veces requestSi falla, el usuario lo sabe y reenvía. Aún así, mejor cola

La regla práctica: si el trabajo puede fallar por un tercero y el usuario ya ha hecho la acción irreversible (pagar, inscribirse, publicar), no puede vivir solo en el request. Tienes que poder repetirlo sin pedirle que pulse otra vez.

Jobs, reintentos y el día que falla de verdad

Encolar no basta. Un job sin reintento, sin tope y sin rastro es un try/catch aplazado. Hay que decidir: cuántas veces, con qué espera, qué se considera error transitorio (timeout, 429, 503) y qué es un error de datos que no se debe repetir (un email mal formado, un ID que no existe).

Idempotencia: el job se puede ejecutar dos veces sin duplicar el efecto. Un mail de «tu entrada» no se manda tres veces porque el worker se cayó a mitad. Un PDF no se genera en bucle. Eso se diseña con un identificador de trabajo y un estado: pendiente, hecho, fallido. Sin estado, cada reintento es una apuesta.

Todo en el request
Cobrar, generar, enviar, responder
Si el mailer tarda 20 segundos, el usuario refresca. A veces duplica el pago. A veces ve un 504 y no sabe si tiene entrada. El log es el de PHP. Nadie reintenta.
Request corto + job
Persistir, responder, trabajar después
El pedido queda como «confirmado, enviando». El job genera y manda. Si falla, reintenta y avisa. El usuario tiene un estado. El soporte tiene una cola, no un hilo de email.

Aquí entra la observabilidad: un job fallido que no deja métrica ni traza es un fallo invisible. Necesitas ver el tamaño de la cola, el tiempo en cola, los reintentos y el error último. Sin eso, «tenemos workers» es una frase de README.

Si el proveedor de correo se cae una hora un sábado, ¿quién se entera y qué se reenvía solo?

Entradas, picos y el día del festival

En Klapper el producto es vender y entregar entradas. El clic de compra no puede esperar a renderizar un PDF y a que el SMTP conteste. El request confirma el pedido. El trabajo de generar, enviar y, si toca, notificar, va detrás. No es sofisticación: es no acoplar el cobro al mailer. Un festival o una sala no te espera a que el worker «ya se pondrá».

En Mallorca Live Festival la web aguanta informar, emocionar y vender en un calendario con picos. No todo pico pide una cola: el HTML se aguanta con caché, CDN y un hosting que no sea shared. La cola aparece cuando, encima del tráfico, hay trabajo de escritura —newsletter, imports de lineup, generación de assets, envíos—. Mezclar las dos conversaciones (servir páginas vs. procesar jobs) es el error. Una no sustituye a la otra.

Emails transaccionales: siempre candidatos a cola. El usuario ya hizo la acción. El mail puede esperar segundos, no fallar en silencio.
PDFs y documentos: CPU y memoria. En el request compiten con quien solo quiere ver una página.
Picos de lectura: primero caché y hosting. La cola no sirve HTML más rápido.
Integraciones: un ERP lento no se espera en el checkout. Se encola y se reconcilia con estado.

Qué no meter en cola (aún) y qué no convertir en microservicio

Una cola es un proceso más que hay que operar: workers, supervisor, disco o Redis, alertas cuando la cola crece. Si tu web manda veinte correos al mes y genera un PDF de vez en cuando, un job síncrono bien acotado —con timeout y log— puede bastar. La complejidad se paga todos los días, no el día del diseño.

Tampoco hace falta un servicio aparte para cada job. El debate monolito frente a microservicios no se resuelve porque encoles el mail. Un worker en el mismo deploy, la misma base y la misma observabilidad es el sitio razonable para la mayoría de webs a medida. Extraer un microservicio de «emails» porque sí es otra factura de red, de contrato y de deploy. La cola es un patrón. El microservicio es una frontera de equipo. No las mezcles.

La cola crece y nadie mira
Workers caídos un domingo. El checkout parece fino. Los mails salen el lunes. Sin alerta de profundidad de cola, el segundo plano es un cajón.
Todo es asíncrono, incluso lo que el usuario espera
«Tu factura se está generando» para un PDF de 200 ms es teatro. La cola es para lo que duele o falla. No para todo lo que se pueda encolar.

Cómo saber si tu web ya lo necesita

Tres señales honestas. Una: habéis tenido un incidente en el que el cobro o el alta existían y el email o el documento no. Dos: un proceso de admin (import, export, regenerar) tumba o ralentiza el front. Tres: estáis a punto de añadir el segundo o tercer tercero en el mismo request de checkout o de publish.

01
Inventario
Qué hace cada request además de leer o escribir una fila. Mail, PDF, HTTP de terceros, ficheros.
02
Separar irreversible
Lo que el usuario ya hizo (pago, alta) se persiste ya. Lo demás se puede reintentar.
03
Un worker, pocos jobs
Empieza por el mail y el documento. No por un bus de eventos. Observa la cola.
04
Estado en la UI
«Enviando», «listo», «error, reintentamos». El segundo plano también se diseña.

En Truman no vendemos una pila de colas. Vendemos un sistema que aguanta el oficio. A veces eso es un worker en el mismo monolito y tres jobs con nombre. A veces, más adelante, un bus. El orden es el de siempre: primero el producto que responde y deja rastro; la complejidad, cuando el request ya no puede con ella.

Dani Marquina

El request HTTP es un mostrador. No es una fábrica. Si detrás del clic estás imprimiendo, llamando a tres APIs y rezando al SMTP, no tienes un problema de «escalar». Tienes el trabajo en el sitio equivocado.

Dani Marquina · Founder, Truman Digital

Antes de encolar (o de no hacerlo), verifica esto

Checklist de colas y jobs
  • ¿Has listado qué hace cada request además de persistir el dato esencial?
  • ¿El cobro o el alta sobreviven si el mail o el PDF fallan?
  • ¿Los jobs son idempotentes y tienen un estado visible?
  • ¿Hay reintento con tope y distinción entre error transitorio y de datos?
  • ¿Alguien recibe una alerta si la cola crece o el worker se para?
  • ¿Estás usando la cola para trabajo pesado, no para servir HTML más rápido?
  • ¿El usuario ve un estado («enviando», «listo») cuando el trabajo va detrás?
  • ¿Un worker en el mismo deploy basta, o de verdad necesitas otro servicio?

Preguntas frecuentes sobre colas y procesos en segundo plano

¿Cuándo una web a medida necesita colas y jobs?

Cuando el request hace trabajo que puede fallar por un tercero o tardar más de lo que un usuario espera: correos, PDFs, llamadas a APIs, imports. Si eso ocurre después de un pago o de un alta, ya no es opcional. Si tu web solo muestra páginas y un formulario simple, puede esperar.

¿Hace falta Redis o un microservicio para tener colas?

No por definición. Hace falta un sitio donde persistir el job y un proceso que lo consuma. Redis, una tabla o el sistema de colas del framework valen si se operan. El microservicio aparece cuando hay un equipo y un contrato que lo justifiquen. No cuando quieres «arquitectura moderna».

¿Qué es un job idempotente?

Uno que puedes ejecutar dos veces y el efecto de negocio ocurre una. No dos mails iguales, no dos cargos, no dos PDFs contradictorios. Se consigue con un identificador estable y un estado «ya hecho». Sin eso, el reintento es peligroso.

¿Las colas mejoran los Core Web Vitals?

Solo de forma indirecta: si dejas de hacer trabajo pesado en la petición que pinta la página, esa petición puede ser más corta. El LCP de la home no se arregla con workers. Se arregla con hosting, caché e imágenes. No uses la cola como parche de rendimiento de front.

Si el checkout o el admin hacen demasiado en la misma petición, mapeamos qué sale del request y qué se reintenta. Sin inventar un microservicio para un mail.
Revisar el trabajo del request

Sobre el autor

Dani Marquina

Dani Marquina

Founder & CTO

Cuéntanos tu proyecto

Nos dices en qué punto estás y te contestamos con franqueza: si podemos ayudarte, te diremos por dónde empezaríamos. Sin compromiso.

Qué pasa después

  1. 01

    Leemos y analizamos tu proyecto

    Revisamos todo lo que nos cuentas y lo entendemos antes de responder. Equipo técnico desde el primer día, sin intermediarios.

  2. 02

    Preparamos una propuesta

    Personalizada, con alcance, enfoque y estimación. No genérica.

  3. 03

    Una llamada para alinear

    Sin presión. Aclaramos dudas y decidís si tiene sentido avanzar.

Hablamos por WhatsApp