Centro de ayuda

Troubleshooting

pg_cron no dispara los jobs programados

Diagnóstico y solución cuando los jobs de pg_cron (recordatorios, digest) no se ejecutan en Supabase.

Actualizado: 2026-05-05

pg_cron no dispara los jobs programados

Los recordatorios automáticos y el digest diario usan pg_cron — la extensión de cron jobs de PostgreSQL disponible en Supabase. Si los jobs no corren, los mensajes no se envían aunque los canales estén bien configurados.

Verificar que pg_cron está habilitado

En el SQL Editor de Supabase:


SELECT * FROM pg_extension WHERE extname = 'pg_cron';

Si no devuelve resultados, pg_cron no está habilitado. En proyectos Supabase self-hosted debes habilitarlo manualmente. En proyectos Supabase cloud está disponible en todos los planes desde el editor:

1. Ve a DatabaseExtensions en el panel de Supabase.

2. Busca pg_cron y actívalo.

---

Ver todos los jobs registrados


SELECT
  jobid,
  jobname,
  schedule,
  command,
  active,
  last_run,
  next_run
FROM cron.job
ORDER BY jobname;

Interpretar los resultados

| Columna | Qué revisar |

|---|---|

| active | Debe ser true. Si es false, el job está pausado. |

| last_run | Cuándo corrió por última vez. Si es muy antiguo, el job está fallando silenciosamente. |

| next_run | Cuándo corre próximo. Si está en el pasado, hay un problema con el scheduler. |

---

Ver el historial de ejecuciones


SELECT
  jobid,
  runid,
  job_pid,
  database,
  username,
  status,
  start_time,
  end_time,
  return_message
FROM cron.job_run_details
WHERE jobid = TU_JOB_ID
ORDER BY start_time DESC
LIMIT 20;

Busca en return_message el error exacto. Los errores más comunes son:

| Error | Causa |

|---|---|

| permission denied for table appointments | El rol pg_cron no tiene acceso a la tabla |

| function send_reminder does not exist | La función fue renombrada o eliminada |

| connection limit exceeded | El pool de conexiones está saturado |

---

Recrear los jobs si no existen

Si los jobs se eliminaron accidentalmente:


-- Job de recordatorios 24h (corre cada hora)
SELECT cron.schedule(
  'enviar_recordatorios_24h',
  '0 * * * *',
  $$
    SELECT send_appointment_reminders();
  $$
);

-- Job de digest diario (corre a las 8:00 AM UTC-5 = 13:00 UTC)
SELECT cron.schedule(
  'digest_diario_tenants',
  '0 13 * * *',
  $$
    SELECT send_daily_digest();
  $$
);

> Ajusta la hora del digest a la zona horaria de tus clientes. Si tienes tenants en múltiples zonas horarias, la función send_daily_digest() calcula la hora correcta por tenant internamente.

---

Permisos del rol pg_cron

pg_cron ejecuta los jobs como el rol postgres por defecto. Si tienes RLS habilitado en las tablas, asegúrate de que las funciones send_appointment_reminders() y send_daily_digest() usen SECURITY DEFINER:


CREATE OR REPLACE FUNCTION send_appointment_reminders()
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  -- lógica de recordatorios
END;
$$;

---

Supabase Free Plan — limitaciones

En el plan gratuito de Supabase, el proyecto se pausa automáticamente después de 7 días sin actividad. Un proyecto pausado no ejecuta pg_cron. Para evitar esto:

1. Configura un cron externo (GitHub Actions, cron-job.org) que haga ping a tu API cada 3 días.

2. O actualiza a un plan pago de Supabase.