Thread-per-core
Each worker thread binds to one CPU core and opens its ownSO_REUSEPORT listener socket. The kernel distributes incoming connections across workers automatically. Workers never share mutable state during request processing.
What each worker owns exclusively:
What workers share (read-only or atomic):
io_uring data plane
Arc uses Linux’s io_uring interface rather than epoll or an async runtime like Tokio. This eliminates per-operation syscall overhead. The key io_uring features Arc uses:- SQPOLL — kernel polling thread that drains the submission queue without syscalls from userspace
- Fixed buffers — pre-registered buffer pool; read/write use buffer indices rather than pointers
- Fixed files — pre-registered file descriptor set; eliminates fd table lookup overhead
- Multishot accept — single
acceptSQE that re-arms itself after each connection; no re-submission per accept - Multishot timeout — single timeout SQE for the connection slab timer wheel
Shared configuration and hot reload
All workers share a singleArcSwap<Arc<SharedConfig>>. SharedConfig contains the compiled router, compiled upstreams, plugin catalog, per-route rate limiters, and TLS state. It is immutable after construction.
The hot reload flow:
restart_required_changes(). If any of those fields change, hot reload is rejected.
All config formats are normalized to canonical JSON internally. TOML and YAML files are parsed, converted to a serde_json::Value, keys are sorted, and the result is stored as raw_json: Arc<str> in SharedConfig. This ensures deterministic fingerprinting across cluster nodes.
Request flow
Security layers
Arc applies three independent security layers:Security details
See full detail.

