pradana adnyana
02/27/2026, 6:38 AMMarvin
02/27/2026, 6:38 AMMarvin
02/27/2026, 6:43 AMprefect events stream --run-once
- If you then start a flow, you should see prefect.flow-run.* (and later prefect.task-run.*) events in the stream.
- Emit a test event to confirm ingestion and UI display:
prefect events emit "test.event" --resource-id "marvin-test-123"
You should see this appear in the Event Feed almost immediately.
Common reasons you only see work pool events
- Filters/time window are hiding other events (most common): Reset filters and widen the time range.
- No flows ran in the selected window: Only system events (like work pool updates) would appear. Kick off a flow run and refresh.
- Self-hosted server config is limiting visibility:
- Ensure event streaming and persistence are enabled before you load the Events page:
PREFECT_SERVER_EVENTS_STREAM_OUT_ENABLED=true
PREFECT_SERVER_SERVICES_EVENT_PERSISTER_ENABLED=true
- If you’re behind a reverse proxy, make sure WebSockets to /api/events/out are allowed; otherwise you’ll only see a short backfill when the page loads and miss live updates.
- Historical window and retention can be tightened by settings; defaults that affect visibility:
- Backfill window used by the Event Feed: PREFECT_SERVER_EVENTS_MAXIMUM_WEBSOCKET_BACKFILL (default ~15m)
- Retention: PREFECT_SERVER_EVENTS_RETENTION_PERIOD (default ~7 days)
Ensure your flows actually emit events
- In Prefect 3.x, flow and task state changes emit events automatically; nothing special to enable. You can also send custom events from code if you want to test:
from prefect import flow
from prefect.events import emit_event
@flow
def demo():
emit_event(
event="demo.completed",
resource={"prefect.resource.id": "demo-1"},
payload={"note": "hello from events"}
)
if __name__ == "__main__":
demo()
If you still only see work pool events after these steps, could you share:
- Are you on Prefect Cloud or self-hosted?
- Prefect version (assuming 3.x)?
- A screenshot or description of your current Event Feed filters/time range?
- The output of prefect events stream --run-once while you start a flow run?
Helpful links
- Events concept & structure
- Events REST API (read/filter)
- Event-driven deployments (example)
- Settings reference (server/OSS): https://docs.prefect.io/v3/api-ref/settings-refpradana adnyana
02/27/2026, 7:12 AMversion: '3.9'
services:
postgres:
image: 'postgres:14-alpine'
environment:
POSTGRES_USER: '${POSTGRES_USER:-prefect}'
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-prefect_change_me}'
POSTGRES_DB: '${POSTGRES_DB:-prefect}'
volumes:
- 'postgres_data:/var/lib/postgresql/data'
healthcheck:
test:
- CMD-SHELL
- 'pg_isready -U ${POSTGRES_USER:-prefect} -d ${POSTGRES_DB:-prefect}'
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
redis:
image: 'redis:7-alpine'
command:
- redis-server
- '--appendonly'
- 'yes'
volumes:
- 'redis_data:/data'
healthcheck:
test:
- CMD
- redis-cli
- ping
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
prefect-server:
image: 'prefecthq/prefect:3-latest'
command: "sh -c \" prefect server database upgrade -y && prefect server start --host 0.0.0.0 --no-services \"\n"
ports:
- '4200:4200'
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: 'postgresql+asyncpg://${POSTGRES_USER:-prefect}:${POSTGRES_PASSWORD:-prefect_change_me}@postgres:5432/${POSTGRES_DB:-prefect}'
PREFECT_SERVER_API_HOST: 0.0.0.0
PREFECT_SERVER_API_PORT: 4200
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_MESSAGING_BROKER: prefect_redis.messaging
PREFECT_MESSAGING_CACHE: prefect_redis.messaging
PREFECT_API_URL: '<http://10.101.3.91:4200/api>'
healthcheck:
test:
- CMD
- python
- '-c'
- "import urllib.request as u; u.urlopen('<http://localhost:4200/api/health>', timeout=1)"
interval: 20s
timeout: 10s
retries: 5
start_period: 30s
restart: unless-stopped
prefect-services:
image: 'prefecthq/prefect:3-latest'
command: 'prefect server services start'
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: 'postgresql+asyncpg://${POSTGRES_USER:-prefect}:${POSTGRES_PASSWORD:-prefect_change_me}@postgres:5432/${POSTGRES_DB:-prefect}'
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_API_URL: '<http://10.101.3.91:4200/api>'
restart: unless-stopped
init-prefect:
image: 'prefecthq/prefect:3-latest'
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_URL: '<http://prefect-server:4200/api>'
entrypoint: "sh -c \" echo 'Initializing Prefect...' && sleep 5 && prefect work-pool create default-pool --type process || true && prefect work-pool create ocr-pool --type docker --overwrite || true && echo 'Initialization complete.' \"\n"
restart: 'no'
workers:
image: 'ghcr.io/aidevakasha/outlet-scrape:latest'
command: 'prefect worker start --pool default-pool --type process --limit 5'
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_URL: '<http://prefect-server:4200/api>'
PREFECT_LOGGING_LEVEL: INFO
restart: unless-stopped
ocr-workers:
image: 'prefecthq/prefect:3-latest'
command: "sh -c \"pip install 'prefect[docker]' &&\n prefect worker start --pool ocr-pool --type docker --limit 5\"\n"
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_URL: '<http://prefect-server:4200/api>'
PREFECT_LOGGING_LEVEL: DEBUG
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
restart: unless-stopped
volumes:
postgres_data: null
redis_data: null
ocr_downloads: null
ocr_outputs: null
why my selfhosted prefect event feed less verbosed that local prefect run by python?
``````
@MarvinMarvin
02/27/2026, 7:12 AMMarvin
02/27/2026, 7:14 AMprefect-services uses PREFECT_API_URL: <http://10.101.3.91:4200/api>. From a Docker container, that host IP may not be routable (hairpin/NAT).
- Use the Docker DNS name instead so services hit the API reliably:
# In BOTH prefect-services and workers
PREFECT_API_URL: <http://prefect-server:4200/api>
- I’d also remove or align PREFECT_API_URL in the prefect-server container (it does not need to point at the host IP). Using the same internal URL is safest:
PREFECT_API_URL: <http://prefect-server:4200/api>
2) Ensure event streaming/persistence are enabled and running
- You start the API with --no-services and a separate prefect-services container — that’s fine, but the services must be healthy and connected.
- Add these (explicit) env vars:
# In prefect-server (API container)
PREFECT_SERVER_EVENTS_STREAM_OUT_ENABLED=true
PREFECT_SERVER_EVENTS_MAXIMUM_WEBSOCKET_BACKFILL=PT60M # optional: widen initial backfill
PREFECT_SERVER_EVENTS_RETENTION_PERIOD=P7D # default; adjust if needed
# In prefect-services (services container)
PREFECT_SERVER_SERVICES_EVENT_PERSISTER_ENABLED=true
- Then check logs to confirm the event persister is running:
docker logs <prefect-services-container> | grep -i event
You should NOT see repeated connection errors to the API.
3) Verify the UI WebSocket is connected
- In your browser DevTools → Network → WS, you should see a connection to /api/events/out with 101 Switching Protocols and it should remain “Open”.
- If it immediately closes or fails, you’ll only see a short backfill and miss most live flow/task events. If you’re behind any proxy, ensure WebSockets to /api/events/out are allowed.
4) Quick functional tests
- From any container where PREFECT_API_URL points to `http://prefect-server:4200/api`:
prefect events emit "test.event" --resource-id "marvin-test-123"
prefect events stream --run-once
- You should see your test event in the Event Feed and in the stream output.
- Kick off a flow run; the stream should show prefect.flow-run.Running and then prefect.flow-run.Completed (and prefect.task-run.* as tasks change state).
5) Keep versions aligned
- You’re using prefecthq/prefect:3-latest in some services and a custom worker image elsewhere. Pin a specific 3.x version across all images to avoid protocol drift, e.g.:
image: prefecthq/prefect:3.1.9
And ensure your custom image uses the same Prefect version.
Suggested compose tweaks (key parts only)
```
services:
prefect-server:
image: 'prefecthq/prefect:3.1.9'
command: "sh -c \"prefect server database upgrade -y && prefect server start --host 0.0.0.0 --no-services\""
environment:
PREFECT_API_DATABASE_CONNECTION_URL: 'postgresql+asyncpg://${POSTGRES_USER prefect}${POSTGRES_PASSWORD:-prefect_change_me}@postgres:5432/${POSTGRES_DB:-prefect}'
PREFECT_SERVER_API_HOST: 0.0.0.0
PREFECT_SERVER_API_PORT: 4200
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_MESSAGING_BROKER: prefect_redis.messaging
PREFECT_MESSAGING_CACHE: prefect_redis.messaging
PREFECT_API_URL: 'http://prefect-server:4200/api'
PREFECT_SERVER_EVENTS_STREAM_OUT_ENABLED: "true"
PREFECT_SERVER_EVENTS_MAXIMUM_WEBSOCKET_BACKFILL: "PT60M"
prefect-services:
image: 'prefecthq/prefect:3.1.9'
command: 'prefect server services start'Marvin
02/27/2026, 7:14 AMprefect events stream --run-once while you start a flow run
- A snippet from docker logs prefect-services around “event” lines
- Whether the /api/events/out WebSocket is connected in your browser
Helpful references
- Events overview
- Settings reference (server events, retention, backfill)
- CLI help we verified: prefect events --help (supports stream and emit)pradana adnyana
02/27/2026, 7:41 AMMarvin
02/27/2026, 7:41 AMMarvin
02/27/2026, 7:42 AM<http://prefect-server:4200/api> and in the healthcheck <http://localhost:4200/api/health>. Those angle brackets are Slack formatting; if they make it into your compose env, Prefect will treat them literally and fail to connect.
- Mixed URLs across containers: prefect-server uses PREFECT_API_URL=<http://localhost:4200/api> while prefect-services uses <http://prefect-server:4200/api>. Standardize to the Docker DNS name for all containers.
Do this:
A) Fix the compose (remove angle brackets, quote URLs, unify API URL)
- Update only the lines shown here; everything else can stay as-is.
prefect-server:
environment:
PREFECT_API_URL: "<http://prefect-server:4200/api>"
PREFECT_SERVER_EVENTS_STREAM_OUT_ENABLED: "true"
PREFECT_SERVER_EVENTS_MAXIMUM_WEBSOCKET_BACKFILL: "PT60M"
PREFECT_SERVER_EVENTS_RETENTION_PERIOD: "P7D"
healthcheck:
test:
- CMD
- python
- -c
- "import urllib.request as u; u.urlopen('<http://localhost:4200/api/health>', timeout=1)"
prefect-services:
environment:
PREFECT_API_URL: "<http://prefect-server:4200/api>"
PREFECT_SERVER_SERVICES_EVENT_PERSISTER_ENABLED: "true"
B) Restart clean
docker compose down -v
docker compose up -d
C) Verify the event pipeline
- From your host, explicitly point the CLI at your server and emit a test event:
export PREFECT_API_URL=<http://localhost:4200/api>
prefect events emit "test.event" --resource-id "marvin-test-123"
prefect events stream --run-once
You should see the test event printed. If not, the CLI isn’t reaching your server.
- Check logs for the services:
docker logs <prefect-services-container> | grep -i event
docker logs <prefect-server-container> | grep -i "POST /api/events"
You should see the persister service start and successful POSTs to /api/events.
D) Check the UI WebSocket
- Open the Events page, then in browser devtools → Network → WS, confirm a live connection to /api/events/out. If it fails/closes, you’ll only see a short backfill and miss live events (proxy must allow WebSockets).
E) Sanity: time window and filters
- Clear filters on the Events page, set time to “Last 30 minutes” or more, then emit again.
If it’s still not showing, could you share:
- The output of prefect events stream --run-once right after you emit
- A few lines around “event” from docker logs prefect-services
- Whether the WS to /api/events/out shows as “Open” in the browser
Helpful refs
- Events overview: https://docs.prefect.io/v3/concepts/events
- Settings (server/events): https://docs.prefect.io/v3/api-ref/settings-ref
- CLI we verified: prefect events --help (supports emit and stream)pradana adnyana
02/27/2026, 7:46 AMMarvin
02/27/2026, 7:46 AMMarvin
02/27/2026, 7:47 AM<...> will break connectivity.
- Your API container was set to PREFECT_API_URL: <http://localhost:4200/api> while services used <http://prefect-server:4200/api>. The former is not reachable from other containers; the latter is correct.
- Services not enabled or failing to start
- The event persister must be enabled and able to reach the API DB and Redis.
- WebSocket/backfill looked fine, but without persistence there’s nothing to show.
Two good paths forward
A) Keep monolithic mode (simplest)
- Your current compose runs prefect server start (no --no-services). This runs the API and all services together; since events show now, you’re good.
B) If you want split mode, use a minimal, known-good wiring
- Key rules:
- Use the Docker DNS name everywhere: <http://prefect-server:4200/api>
- Quote all URL env vars; do not include angle brackets
- Enable event services explicitly
- Ensure versions are pinned consistently (avoid 3-latest drift)
Here’s a trimmed split-mode example you can drop in (only the relevant parts shown):
services:
prefect-server:
image: "prefecthq/prefect:3.1.9"
command: "sh -c \"prefect server database upgrade -y && prefect server start --host 0.0.0.0 --no-services\""
ports:
- "4200:4200"
environment:
PREFECT_API_DATABASE_CONNECTION_URL: "postgresql+asyncpg://${POSTGRES_USER:-prefect}:${POSTGRES_PASSWORD:-prefect_change_me}@postgres:5432/${POSTGRES_DB:-prefect}"
PREFECT_SERVER_API_HOST: "0.0.0.0"
PREFECT_SERVER_API_PORT: "4200"
PREFECT_REDIS_MESSAGING_HOST: "redis"
PREFECT_REDIS_MESSAGING_PORT: "6379"
PREFECT_MESSAGING_BROKER: "prefect_redis.messaging"
PREFECT_MESSAGING_CACHE: "prefect_redis.messaging"
PREFECT_API_URL: "<http://prefect-server:4200/api>"
PREFECT_SERVER_EVENTS_STREAM_OUT_ENABLED: "true"
PREFECT_SERVER_EVENTS_MAXIMUM_WEBSOCKET_BACKFILL: "PT60M"
PREFECT_SERVER_EVENTS_RETENTION_PERIOD: "P7D"
prefect-services:
image: "prefecthq/prefect:3.1.9"
command: "prefect server services start"
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: "postgresql+asyncpg://${POSTGRES_USER:-prefect}:${POSTGRES_PASSWORD:-prefect_change_me}@postgres:5432/${POSTGRES_DB:-prefect}"
PREFECT_REDIS_MESSAGING_HOST: "redis"
PREFECT_REDIS_MESSAGING_PORT: "6379"
PREFECT_API_URL: "<http://prefect-server:4200/api>"
PREFECT_SERVER_SERVICES_EVENT_PERSISTER_ENABLED: "true"
Diagnostics to use in split mode
- From the services container, verify it can see the API:
docker exec -it <prefect-services> sh -lc "prefect config view | grep PREFECT_API_URL"
docker exec -it <prefect-services> sh -lc "curl -sf <http://prefect-server:4200/api/health> && echo OK"
- Check logs for the event persister starting and posting events:
docker logs <prefect-services> | egrep -i "event persister|events|error|traceback"
docker logs <prefect-server> | grep "POST /api/events" -n
- Functional check:
export PREFECT_API_URL=<http://localhost:4200/api>
prefect events emit "test.event" --resource-id "marvin-test-123"
prefect events stream --run-onceMarvin
02/27/2026, 7:47 AM