Jobs en segundo plano sin pagar por ejecución: Trigger.dev + Coolify

Cómo corremos los jobs de PideAí con Trigger.dev self-hosted en Coolify y deploy desde GitHub Actions: reintentos, cron y logs, con costo fijo.

2 min de lectura

Compartir WhatsAppLinkedInX
Ilustración de servidores conectados a un panel con tareas programadas, sincronización y alertas

¿Cuánto te va a costar el cron de mañana? Si tus jobs corren en un servicio que cobra por ejecución, no lo sabes hasta que llega la factura.

Todo backend llega a ese punto: hay trabajo que no puede esperar a que un usuario haga clic. En PideAí eran tres cosas: sincronizar la tasa de cambio, mandar recordatorios por WhatsApp y limpiar carritos abandonados.

Las dos salidas de siempre

La primera es armarlo a mano: Redis, una cola, workers, reintentos y algo que te avise cuando falla. Funciona, pero ahora mantienes una pieza más de infraestructura.

La segunda es pagar un servicio gestionado. No mantienes nada, pero cada ejecución suma: un job cada 30 minutos son 1.440 ejecuciones al mes, y eso es uno solo.

Queríamos control total, poco mantenimiento y un costo que no se mueva. Lo encontramos en Trigger.dev self-hosted + Coolify + GitHub Actions.

Qué resuelve Trigger.dev

Trigger.dev es un framework open source para escribir, correr y monitorear jobs en TypeScript. Trae de fábrica lo que, si no, terminas construyendo tú: reintenta las tareas que fallan, las programa con cron, guarda los logs de cada ejecución y deja que una tarea dispare otra para armar flujos completos.

Además, puedes hostearlo tú mismo. Los datos quedan en tu servidor y no pagas por ejecución: pagas el servidor, que ya tenías.

Ejemplo real: la tasa del BCV, cada hora

PideAí vende en Venezuela, así que los precios dependen de la tasa del Banco Central de Venezuela. Esta tarea la busca cada hora y actualiza la tienda:

import { schedules } from '@trigger.dev/sdk/v3';

export const syncExchangeRates = schedules.task({
  id: 'sync-bcv-rates',
  cron: '0 * * * *', // cada hora
  run: async () => {
    const rates = await fetchBCVRates();
    await updateStoreRates(rates);
    console.log('Exchange rates synced successfully.');
  },
});

Si el BCV no responde, Trigger.dev reintenta solo, y en el panel ves cada ejecución con su resultado.

Cómo llega a producción

Diagrama: un git push dispara npx trigger.dev deploy; Coolify aprovisiona y gestiona Trigger.dev, cuyos workers procesan la cola de jobs: tasas de cambio cada hora, limpieza de sesiones diaria y campañas de WhatsApp programadas

La instancia de Trigger.dev (la API y los workers) corre en Coolify, una alternativa open source y self-hosted a Heroku o Vercel. Ahí la levantamos y la gestionamos como cualquier otra app del servidor.

El deploy lo hace GitHub Actions: cada push a main corre npx trigger.dev deploy y los jobs se actualizan sin que nadie toque nada. La URL de la API y el token viven como secrets del repositorio, así que el deploy siempre apunta a nuestra instancia y no a la nube de Trigger.dev.

Qué más corre ahí

Además de la tasa de cambio:

  • Limpieza de sesiones vencidas, una vez al día.
  • Alertas de stock bajo, cada 30 minutos.
  • Campañas de WhatsApp programadas.

Para sumar un job nuevo basta con escribir la tarea y hacer push, y la factura sigue igual.

¿Te sirve a ti?

Si ya tienes un servidor y corres más de un puñado de jobs, probablemente sí. Si no quieres administrar nada, un servicio gestionado sigue siendo razonable: lo que pagas es no tener que mantenerlo.