Instance Affinity
Every target is assigned to exactly one Thorax execution server at a time. That assignment is its instance affinity, and it decides which server dispatches work to the target.
Why targets are pinned
Section titled “Why targets are pinned”In listen (push) mode, Thorax dials the agent (Thorax -> Tarsus :9342) and holds that connection; the owning instance is the one that connected. Pinning the target to one instance means:
- Only one server dispatches to a target, so a command is never delivered twice
- The open connection is reused rather than renegotiated per deployment
- Deployment logs and step state stream back over a single path
The assignment is recorded on the target itself as assigned_thorax_id, together
with the time it was made.
How the assignment is chosen
Section titled “How the assignment is chosen”Targets are assigned when they register. Selection is tenant-aware: a target is only ever assigned to a Thorax instance permitted to serve its tenant, so multi-tenant isolation holds across the execution tier as well as the API.
What happens when a server goes offline
Section titled “What happens when a server goes offline”Affinity is not permanent. Two services work together to move targets off a dead server:
- Instance cleanup checks every 30 seconds and marks a Thorax instance offline once it has missed heartbeats for 60 seconds.
- Thorax reassignment then finds every target still pointing at an offline
instance, selects a new one for each — again tenant-aware — updates
assigned_thorax_id, and publishes the change so connected agents learn about it.
Agent targets use a longer liveness window than Thorax instances (360 seconds), deliberately set above the maximum agent heartbeat interval so that a slow agent is not mistaken for a dead one.
What an operator sees
Section titled “What an operator sees”- Targets move between servers on their own; no manual step is required
- Work already queued for the old instance is not lost — see Competing Consumers for how it is reclaimed
- Reassignment is recorded against the target
Related
Section titled “Related”- Competing Consumers — how several servers share one dispatch queue
- Listen vs Poll Mode — why listen-mode targets hold a connection
