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 Database → Extensions 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.