Rasmus Simmelkjær Berntsen
11/11/2025, 5:40 AMMarvin
11/11/2025, 5:40 AMMarvin
11/11/2025, 5:49 AMprefect --version
- Database: are you on PostgreSQL or SQLite? For production and lots of events/automations, PostgreSQL is required — SQLite will cause locking delays.
- Deployment: Docker Compose vs Kubernetes, and how many “services” instances are running (generally only one services instance should run the triggers).
2) Make sure the services that power automations are running
- In self-hosted, automations are evaluated by the services process (ReactiveTriggers, ProactiveTriggers, Actions, EventPersister).
- If you use Docker Compose, there should be a “prefect-services” container. On K8s, the “services” deployment/pod needs to be up and healthy.
3) Check config (timing/loops)
- View effective settings:
prefect config view --show-defaults
Useful keys to look for/tune:
- Triggers service
- PREFECT_SERVER_SERVICES_TRIGGERS_ENABLED (should be true)
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_HEARTBEAT_INTERVAL_SECONDS (default ~5)
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_RECONNECT_INTERVAL_SECONDS (default ~10)
- Foreman (can add seconds to latency on state-driven automations)
- PREFECT_SERVER_SERVICES_FOREMAN_LOOP_SECONDS (default ~15; consider 5–10)
- Scheduler (doesn’t directly control automations but worth checking)
- PREFECT_SERVER_SERVICES_SCHEDULER_RECENT_DEPLOYMENTS_LOOP_SECONDS (default ~5)
- DB timeout (timeouts cause retries/backoff)
- PREFECT_SERVER_DATABASE_TIMEOUT (consider 30–60s if your DB is under load)
- Timezone/clock consistency
- Set TZ=UTC everywhere; ensure NTP is syncing on all nodes
Docs for settings and automations:
- Settings reference
- Automations and event triggers
- Self-hosted (Docker Compose)
- Helm (Kubernetes)
4) Look for proactive vs reactive automations
- Reactive triggers fire near real-time on events (via Postgres LISTEN/NOTIFY).
- Proactive triggers (e.g., “if X does NOT happen within N minutes”) are evaluated periodically; their effective “within” plus service loop adds inherent delay. If your automations look for the absence of an event, some delay is expected based on the window you set.
5) Log-level and indicators
- Temporarily increase logs to debug in the services container:
- PREFECT_LOGGING_LEVEL=DEBUG
- Look for entries showing “reactive evaluation”/“proactive evaluation,” “trigger fired,” and “action executed” — if triggers fire immediately but actions execute later, the delay is in the actions path.
6) Database health
- If using SQLite, this is very likely the cause — please switch to PostgreSQL.
- If using PostgreSQL, ensure it has enough resources and connections, and that you’re not seeing lock waits/timeouts during peak times.
Example Docker Compose tuning (services container)
services:
prefect-services:
environment:
- PREFECT_SERVER_SERVICES_TRIGGERS_ENABLED=true
- PREFECT_SERVER_SERVICES_FOREMAN_LOOP_SECONDS=5
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_HEARTBEAT_INTERVAL_SECONDS=5
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_RECONNECT_INTERVAL_SECONDS=10
- PREFECT_SERVER_DATABASE_TIMEOUT=30
- TZ=UTC
A few clarifying questions to help me pinpoint this for you:
- What Prefect version are you on?Marvin
11/11/2025, 5:49 AMRasmus Simmelkjær Berntsen
11/11/2025, 5:52 AMMarvin
11/11/2025, 5:52 AMMarvin
11/11/2025, 5:53 AMPREFECT_SERVER_SERVICES_TRIGGERS_ENABLED=true.
Docs:
- Prefect Helm (Kubernetes)
- Services overview via Docker Compose (concepts carry over)
2) PgBouncer (or any DB proxy) in transaction pooling mode
- Reactive triggers rely on PostgreSQL LISTEN/NOTIFY, which requires a persistent session connection.
- If you connect to Postgres through PgBouncer in transaction pooling mode, LISTEN/NOTIFY will not work reliably — the listener won’t receive notifications, and your system will fall back to the slow, periodic sweep.
- Action: If you use PgBouncer, switch the connection for the services pod to session pooling or bypass PgBouncer and connect directly to Postgres for the services pod.
3) Multiple services replicas
- Running more than 1 replica of the services (triggers) can cause contention or odd behavior; it won’t usually cause a 15-minute lag, but it’s not recommended.
- Action: Scale services to 1 replica.
4) Postgres connectivity and settings on the services pod
- Ensure the services pod has the same DB URL as the API and can reach it.
- Useful environment variables:
- PREFECT_SERVER_SERVICES_TRIGGERS_ENABLED=true
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_HEARTBEAT_INTERVAL_SECONDS=5
- PREFECT_SERVER_SERVICES_TRIGGERS_PG_NOTIFY_RECONNECT_INTERVAL_SECONDS=10
- PREFECT_SERVER_DATABASE_TIMEOUT=30 (or 60 if you see timeouts)
- If the listener repeatedly disconnects/reconnects, you’ll see delays.
Settings reference:
- Settings reference
- Automations and event triggers
5) Clock skew
- If system clocks differ across pods/DB by minutes, reactive evaluation can appear late.
- Action: Ensure NTP is enabled and all pods/nodes/DB are synced; set TZ=UTC on all containers.
What to check next (quick checklist)
- Do you have a “services” Deployment/Pod running in your cluster? Is it healthy? How many replicas?
- Are you routing Postgres through PgBouncer or a proxy? If yes, is it using transaction pooling? If so, connect the services pod with session pooling or directly to Postgres.
- Check services pod logs:
- Look for lines indicating “ReactiveTriggers” started and “listening for pg_notify.”
- Look for repeated reconnects or errors related to LISTEN/NOTIFY or DB locks/timeouts.
- Verify effective config:
- In any Prefect container/pod:
prefect config view --show-defaults
Confirm the triggers service is enabled and the DB timeout is reasonable.
If you can share:
- Whether you have a separate “services” deployment and how many replicas it has
- Whether PgBouncer (or another proxy) sits between Prefect and Postgres, and its pooling mode
- Any relevant errors/warnings from the services pod logs around triggers/pg_notifyMarvin
11/11/2025, 5:53 AMNate
11/11/2025, 5:54 AMprefect server start processes)?Nate
11/11/2025, 5:54 AMRasmus Simmelkjær Berntsen
11/11/2025, 6:15 AMRasmus Simmelkjær Berntsen
11/11/2025, 6:36 AMMarvin
11/11/2025, 6:36 AMMarvin
11/11/2025, 6:37 AMPREFECT_SERVER_SERVICES_TRIGGERS_ENABLED=true
- If you are using PgBouncer, the services pod must use session pooling (or connect directly to Postgres) so LISTEN/NOTIFY works; transaction pooling will break real-time delivery and cause the kind of 10–15 minute lag you’re seeing.
Good refs
- Kubernetes/Helm deployment
- Automations and event triggers
- Settings reference
If you’d like, I can share a minimal K8s layout checklist for the two Deployments and what to set on each.Nate
11/11/2025, 6:57 AMI am running 2 servers, and no redisyou may want to check out this. if you're using multiple servers and then you need run redis as the messaging broker so all servers see the same events