With SO_REUSEPORT, several Linux TCP sockets can listen on the same local address and port at the same time. Incoming connections are assigned to a member of that reuseport group before an application calls accept(). The application no longer needs one shared listening socket as the sole handoff point between the network stack and multiple workers.
That changes more than bind eligibility. It moves connection distribution into the kernel and gives each listener its own socket identity and accept path. The resulting architecture has different queueing, lifecycle, and routing properties from a design in which many workers compete on one listening socket.
The option creates a group of distinct listeners
Linux permits multiple AF_INET or AF_INET6 sockets to bind an identical address when SO_REUSEPORT is enabled on every participating socket before bind(). For TCP, each socket later enters the listening state independently.
The sockets are not aliases for one file description. Each listener is a separate socket. A process can close one listener without closing the others, attach listener-specific state where an interface permits it, and call accept() against one member rather than against a shared descriptor.
Linux also constrains group membership. Processes binding the same address through this mechanism must have the same effective user ID, which prevents an unrelated user from joining an existing reuseport group merely by setting the option.
The architectural boundary is therefore a set of eligible listeners associated with one local endpoint, not one listener referenced by several workers.
Selection occurs before accept
Without reuseport, a common multi-worker arrangement has one listening socket shared across threads or processes. Completed connections become available through that socket, and workers compete or coordinate around calls to accept().
A reuseport group changes the point of selection. Linux selects a listening socket from the group for incoming traffic. The worker that owns or polls that listener later accepts connections assigned to it.
This means accept() is not the load-balancing operation. By the time a particular listener reports an acceptable connection, kernel-side selection has already placed that connection on the path associated with that listener.
That distinction matters when diagnosing imbalance. A worker can have an empty accept path while another listener has pending work. Treating the group as one interchangeable queue hides the fact that assignment happened earlier.
Equal bind addresses do not imply a portable distribution contract
SO_REUSEPORT is a Linux socket option with implementation-specific selection behavior. The interface permits kernel distribution across the group, but applications should not infer a universal round-robin contract from the shared address.
Connection placement can depend on kernel selection logic and the packet or flow information available to that logic. The important stable property for application design is that the kernel chooses a member of the eligible group, not that each member receives an exact fraction of connections over any chosen interval.
This limits what a server can infer from short-term listener counts. Unequal counts do not, by themselves, prove a broken listener, and equal counts are not a contractual invariant.
The same caution applies across operating systems. A socket option with a similar name can have different binding or distribution semantics. Code that relies on Linux reuseport behavior needs an explicit platform boundary.
BPF can turn default selection into policy
Linux exposes classic and extended BPF hooks for reuseport groups. A reuseport BPF program can influence which socket receives traffic, subject to the documented program type and return semantics.
For the index-based interface, sockets are numbered according to their order of entry into the group: bind order for UDP and listen order for TCP. Group membership is not permanently indexed. When a socket leaves, Linux can move the final socket into the removed member’s position.
That lifecycle rule makes an index a position in the current group rather than a durable worker identity. A policy that assumes index 2 permanently names one process can become incorrect after membership changes unless the surrounding design accounts for reindexing.
New sockets added to a reuseport group inherit the group’s BPF program. Replacing the program through a member applies the current program to the group. Policy attachment is therefore group-oriented even though the listeners remain distinct sockets.
Listener lifecycle becomes part of routing behavior
In a shared-listener design, adding a worker can leave the listening socket itself unchanged. The new worker starts accepting from an already existing endpoint.
With one reuseport listener per worker, worker lifecycle can also change group membership. Starting a worker can add a listener; stopping one can remove a listener. If kernel selection or an attached BPF program depends on group composition, those events alter the routing set.
This creates a boundary between connection assignment and application deployment state. Existing accepted connections remain associated with their established sockets, while later arrivals are selected from the listeners eligible at that later point.
A graceful shutdown therefore has at least two distinct concerns: stop receiving new assignments and drain connections already owned by the worker. Closing or otherwise removing a listener addresses the first concern but does not erase established connections already accepted by that process.
Per-listener queues change overload visibility
Separate listeners also mean separate accept paths. A server that exports only aggregate connection counts can miss concentration on one member of the group.
Suppose four workers each own a reuseport listener. If one worker stops calling accept() while remaining in the eligible group, traffic can still be assigned to its listener according to the active selection policy. Healthy workers accepting promptly do not automatically consume pending connections from that other listener as though all four shared one accept queue.
The exact TCP queue behavior and overflow consequences depend on kernel state, configuration, and protocol processing. The design-level consequence is narrower: independent listeners create independent places where pending work and application progress can diverge.
Operational signals are therefore more informative when they retain listener or worker identity instead of collapsing the group into one endpoint-level number.
Reuseport is distribution, not application coordination
Kernel-side listener selection does not coordinate application state across workers. It does not serialize updates, share caches, preserve session affinity beyond properties supplied by the selection mechanism, or make worker-local state globally visible.
A service that requires a connection to reach a particular stateful worker needs a routing rule that actually encodes that requirement, or it needs to move the relevant state outside worker-local memory. Default reuseport distribution alone supplies neither guarantee.
Likewise, reuseport does not replace admission control. Multiple listeners can distribute arrival work while every worker still depends on the same downstream database, file descriptor budget, memory pool, or CPU capacity.
The option changes where one routing decision occurs. It does not remove the capacity boundaries after that decision.
The listener is part of the scheduling topology
A single shared listening socket makes worker competition visible at accept(). A reuseport group moves the earlier scheduling decision into the kernel and makes listener membership part of the server topology.
That can remove an application-level accept handoff and align one listener with one worker, but it also creates separate listener state that must be observed and managed as such. Group membership changes can affect future assignment, BPF policies must account for mutable indices, and overload on one listener is not equivalent to backlog on a single shared socket.
The useful abstraction is not simply several processes bound to one port. It is a kernel-managed routing group whose members remain distinct listening sockets.