#5448·webiny-js

Self-hosted event handlers: unify + harden the internal self-callback URL (port)

Author: adrians5jCreated Jul 21, 2026Updated Jul 21, 2026

Follow-up from PR #5414.

The scheduler and background-tasks event handlers each POST to an internal route on the same server (self-callback). Both build that base URL ad-hoc:

  • packages/api-event-handler-server/src/scheduler/schedulerServer.ts: const serverBase = () => \http://localhost:${process.env.PORT || "3002"}`;`
  • packages/background-tasks-server/src/service/WorkerTaskService.ts: const port = process.env.PORT || DEFAULT_SERVER_PORT; (DEFAULT_SERVER_PORT = 3000)

Issues

  1. Inconsistent hardcoded fallbacks — scheduler 3002, bg-tasks 3000, for the same concept.
  2. Fallback masks failurerunApiServer always injects the resolved port as process.env.PORT (it collapses WEBINY_API_PORT → PORT → findFreePort(3002) before spawning), so the || fallback is effectively dead. If it ever fired, a silent POST to a guessed port would fail quietly. Prefer failing loud (throw/log) over guessing.
  3. Duplication — the "URL back to myself" logic is copy-pasted across the two handlers.

Note (not a bug)

Reading process.env.PORT is CORRECT — it's the resolved listening port runApiServer injects. Do not switch these to WEBINY_API_PORT; that's the user-facing input knob and is often unset when the server binds a findFreePort port.

Direction

  • A single shared helper (e.g. selfBaseUrl()) reused by both handlers.
  • Read process.env.PORT; if unset, throw/log loudly instead of falling back to a magic number.
  • Consider whether the host (localhost) should be configurable — fine as-is for a same-process self-callback.

Scope: small infra cleanup. Not blocking #5414.

Related

  • PR #5414
  • #5429, #5433, #5446