Horizon queues

One Horizon instance in the ingestion application consumes every production queue on kraite. It is the execution side of scheduled, trading, indicator, stream, and web-originated work.

This is the subsystem lens. See the Kraite host for the physical service boundary.


Queue layout

Logical lanePhysical queueProcessesPurpose
positionskraite-positions2Position state machines
orderskraite-orders3Exchange order round-trips
prioritykraite-priority1Urgent recovery work
cronjobskraite-cronjobs2Scheduled lifecycle entry points
indicatorskraite-indicators3Market-data and indicator work
user-data-streamkraite-user-data-stream1Binance account events
webkraite-web1Mail, notifications, and web jobs
kraitekraite1Direct host-targeted work

Dispatch flow

  1. A command or event creates a step on a logical lane.
  2. StepRouter selects the production candidate kraite.
  3. The router emits the physical kraite-* queue name.
  4. Horizon executes the job and the step records its terminal or retry state.

An inactive exchange is filtered before this flow creates current work. A permanent account or whitelist failure can deactivate the account before dispatch; a temporary rate window waits and retries.

Why one instance

Single runtime owner

Admin and the public site share the core package but do not run duplicate Horizon supervisors. Their background jobs use the web lane consumed by ingestion. This prevents a web checkout from accidentally consuming trading queues under different application configuration.

Capacity rule

Fourteen workers are the starting private-use budget. Orders receive the largest lane because their state machines are exchange-call heavy. Indicator and cron work remain bounded so they cannot exhaust memory or starve position protection on the four-core, 8 GB host.

Rate limits are still coordinated in Redis. Extra processes would add local concurrency, not permission to exceed provider budgets.

Isolation and naming

APP_ENV=production selects product behavior. HORIZON_ENV=kraite selects the one production supervisor map. A unique Horizon prefix keeps its internal metadata separate from ordinary cache and queue keys.

The deploy topology gate proves that configuration and the servers table both name kraite. A mismatch aborts before long-running processes restart.

What Horizon does not own

  • The scheduler decides when commands create work.
  • DispatchDaemonCommand decides which step becomes runnable.
  • Binance stream commands receive live exchange events.
  • The step-dispatcher package owns step state transitions.
  • MySQL owns durable domain state; Redis owns transient queue state.