Most load balancers sit in the middle of every conversation. A client sends a request, the load balancer forwards it to a backend server, the backend replies to the load balancer, and the load balancer relays the response back to the client. Every byte in both directions passes through the same box.
For a great many workloads that is perfectly fine. But for services where responses dwarf requests — video streaming, large file downloads, bulk API exports — it means the load balancer spends most of its capacity shovelling response traffic it adds no value to. Direct Server Return (DSR) removes that bottleneck entirely.
The core idea
With DSR, inbound requests still pass through the load balancer, but outbound responses travel directly from the backend server to the client. The flow looks like this:
- The client sends a request to the Virtual IP (VIP) address.
- The load balancer receives it and selects a backend using the configured scheduling algorithm.
- The load balancer forwards the packet to that backend, preserving the original destination IP — the VIP.
- The backend processes the request and sends its response directly to the client, using the VIP as the source address.
- The client receives a response that appears to come from the VIP, unaware a different machine produced it.
The trick is in step 4. Because the backend answers with the VIP as its source address, the client’s TCP stack sees a perfectly ordinary conversation with one IP address. It never knows the return path skipped the load balancer.
For this to work, each backend must be configured to accept traffic addressed to the VIP — typically by adding the VIP to a loopback interface — and must be prevented from answering ARP queries for that address, so it does not compete with the load balancer for ownership of the VIP on the network.
Why bother?
The load balancer stops being a bandwidth bottleneck. With responses bypassing it, the load balancer only handles the comparatively tiny inbound request stream. For workloads where responses are orders of magnitude larger than requests, this can reduce the load balancer’s throughput requirement by 90% or more.
Lower latency on the return path. Responses take a direct route from backend to client, removing a hop.
More backends per load balancer. Freed from processing response traffic, a single appliance can front a far larger server pool than a full-proxy configuration allows, with obvious cost benefits.
In Tula, DSR is a Layer 4 feature, implemented in the nftlb engine that runs inside the Linux kernel’s nftables framework — so even the inbound forwarding path carries minimal overhead.
Two flavours: L2 and L3
Tula supports two DSR modes, and the choice comes down to network topology.
Layer 2 DSR (MAC rewriting)
In L2 mode, the load balancer rewrites the destination MAC address of each incoming Ethernet frame to that of the chosen backend. The IP headers are untouched — the destination IP is still the VIP. The frame is delivered by ordinary Ethernet switching.
This is the simplest and lowest-overhead mode: no tunnels, no encapsulation, no MTU concerns. The constraint is that the load balancer and every backend must share the same Layer 2 broadcast domain. If your backends span subnets or sites, L2 DSR cannot reach them.
Layer 3 DSR (IP-in-IP tunnelling)
In L3 mode, the load balancer encapsulates the original packet inside an IP-in-IP (IPIP) tunnel addressed to the backend’s routable IP. The backend decapsulates it on a tunnel interface, revealing the original packet with the client’s source IP and the VIP as destination, then replies directly to the client as before.
Because the encapsulated packet is routed like any other IP traffic, backends can live on different subnets, VLANs, or even in different data centres. The costs are modest: a 20-byte outer IP header on every inbound packet, and some care around MTU (a 1,500-byte network MTU leaves 1,480 bytes for the inner packet). See the L3 DSR documentation for the MTU mitigation options.
What backend configuration looks like
Each Linux backend in an L2 DSR pool needs the VIP on its loopback interface and ARP suppression for that address:
ip addr add 10.0.1.100/32 dev lo
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
arp_ignore=1 stops the server answering ARP requests for addresses that are not on the interface the request arrived on, and arp_announce=2 makes it use the best local address when issuing ARP requests — together preventing the backend from claiming the VIP on the network. Persist both in /etc/sysctl.d/99-dsr.conf so they survive a reboot.
L3 backends additionally need the ipip kernel module and a tunnel interface; the DSR configuration guide walks through both variants step by step.
When DSR is the wrong tool
DSR’s power comes from the load balancer never seeing response traffic — which is also its fundamental limitation.
- No response modification. The load balancer cannot inspect, rewrite, or compress responses. HTTP header insertion on responses is off the table.
- No Layer 7 features. DSR operates at Layer 4. Content-based routing, cookie persistence, and HTTP health checks all require a full proxy path and are unavailable.
- No SSL offload on responses. If responses must be encrypted, the backends themselves must handle TLS end to end.
- Backend configuration is on you. Every backend needs the loopback VIP and ARP settings, which adds operational surface area compared with a plain NAT-mode VIP.
If your service is an ordinary web application that benefits from host-based routing, sticky sessions, or SSL termination at the edge, a standard Layer 7 VIP is the better fit. DSR earns its keep on asymmetric, high-throughput workloads: media delivery, software distribution, object storage origins, and high packet-rate game or real-time services.
The rule of thumb
Ask one question: are my responses much larger than my requests, and do I need the load balancer to do anything clever with them?
If the answers are "yes" and "no" respectively, DSR will likely cut your load balancer’s bandwidth requirement dramatically for very little ongoing effort. If you need application-layer intelligence, stay with a full-proxy L7 VIP and let the load balancer see both directions of the conversation.
To try it yourself, the Direct Server Return overview covers the concepts in more depth, and the mode-specific guides for L2 and L3 DSR include the full configuration steps for both the appliance and your backends.