Server rack with network cables and glowing status LEDs in a data center environment
eBPF Use Cases
William  

Katran XDP Load Balancer: Kernel-Native Packet Forwarding

Katran is Facebook's open-source Layer 4 load balancer built on XDP and eBPF, and the Facebook Katran XDP data plane earns its reputation for one reason: it forwards packets inside the kernel, at the NIC receive path, before they ever climb into the network stack. That is why it holds under traffic that sinks IPVS and other userspace or netfilter-based balancers. It is not a drop-in appliance. Running it means reading the source, knowing whether your NIC driver supports XDP, and being ready to debug with bpftool, strace, and the kernel ring buffer when an abstraction leaks. If you want a load balancer you never think about, this isn't it. If you want one that holds at Facebook-grade scale and you'll own the operational depth, Katran is the right call.

Last updated: 2026-07-21

I write from hands-on experience and aim to make this practical: lab to service edge, transparent debugging, and tools you already know.

What is Katran and what problem does it solve

Katran solves a single hard problem: present a huge server fleet as one virtual IP (VIP) at the edge, and forward packets to it without a per-flow bottleneck. Facebook built it for its Points of Presence, the racks that terminate traffic close to users around the world. At that scale, a userspace balancer spends most of its CPU copying packets and taking locks. Katran skips both.

The trick is where it runs. Instead of a daemon reading sockets, Katran attaches an eBPF program to the XDP hook. Switches announce the VIP with BGP and use equal-cost multi-path (ECMP) routing to spread flows across Katran instances. Each instance then picks a backend on its own, with no cross-machine state sync. So you scale by adding boxes, not by coordinating them.

Call the category what it is: an eBPF load balancer. Katran is the reference example, open-sourced by Facebook, and it is worth studying even if you never deploy it.

How does Katran use XDP and eBPF to forward packets

The whole design lives at the eXpress Data Path (XDP) hook. XDP runs your eBPF program the instant the driver pulls a packet off the RX ring, before the kernel allocates an sk_buff or does any stack processing. For each packet the program returns a verdict: XDP_DROP, XDP_PASS, or XDP_TX. Katran mostly rewrites and retransmits, so it never pays the cost of a full trip through the stack.

There are two ways to attach it. Native (driver) XDP runs inside the NIC driver and is the fast path you actually want. Generic XDP runs higher up as a fallback when the driver has no XDP support, and it is slower because the kernel has already done work by then. Check which mode you got, because it decides whether the numbers hold.

Katran leans hard on per-CPU lockless maps for packet processing. Each CPU core keeps its own copy of the map, so cores never contend for a lock on the hot path. That is the difference between linear scaling across RX queues and a balancer that flatlines at four cores.

If you want the mechanism behind this in isolation, I've written more on using XDP for low-latency processing.

How Katran's Layer 4 architecture actually works

Working at Layer 4 means Katran never parses HTTP or terminates TLS. It looks at the IP and TCP/UDP headers, picks a backend, and forwards. That is the trade: no content routing, no SSL termination, but a fraction of the per-packet cost of an application proxy.

Backend selection uses an extended version of Maglev hashing. Maglev gives you a stable, near-uniform mapping from flow to backend, and it shifts gracefully when the backend set changes, so adding or draining one server does not reshuffle every existing flow. Katran also keeps a small LRU cache of recent flows to pin them. Under memory pressure it drops the cache and recomputes the hash instead, which trades a little CPU for bounded memory.

Once a backend is chosen, Katran encapsulates the packet. It wraps the original in an outer IP header (IP-in-IP) addressed to the real server, and varies the outer source address per flow. That variation matters: it lets the receiving NIC's receive-side scaling (RSS) spread flows across queues and cores instead of piling them on one. Encapsulation and RSS working together is what keeps the backend side from becoming the new bottleneck.

How does Katran distribute virtual IPs to backend servers

Each VIP maps to a pool of real servers, and Katran forwards using Direct Server Return (DSR). The backend hosts the VIP on a loopback interface and replies straight to the client. So Katran only ever sees inbound traffic. For request-heavy, response-heavy services like video, that halves the load the forwarder carries.

Health and pool changes are the part people underestimate. When a backend goes unhealthy or you drain it, the consistent hashing means only flows that mapped to that server move; everything else stays pinned. That is the whole point of Maglev over naive modulo hashing, where losing one backend renumbers all of them and kills every established connection.

DSR has a sharp edge. Return traffic bypasses Katran entirely, so if your routing or reverse-path filtering is wrong, replies vanish and you'll blame the balancer. Validate the return path before you trust it. And plan MTU: the outer IP header eats bytes, so the encapsulated packet is larger than the client's. If you don't lower the MSS or size the MTU for it, you get silent drops on full-size packets and a maddening intermittent failure. Katran also does not handle fragmented packets or IP options, so design them out.

What makes Katran faster than traditional software load balancers

Network switch with multiple ethernet cables connected showing data traffic routing

The speed is not sleight of hand, it is arithmetic. A userspace balancer copies each packet from kernel to user memory and back, and locks shared state. Katran does neither. It processes the packet in place at XDP, reads and writes per-CPU maps with no locks, and retransmits from the same context. Fewer copies, no lock contention, less CPU burned per packet.

That per-packet saving is the whole story at high packets-per-second (pps). When each packet costs a few hundred nanoseconds less, and you're doing millions per second per box, you fit far more traffic on the same hardware. The per-CPU lockless maps are what let throughput climb as you add RX queues instead of plateauing.

Here is what actually limits you in practice:

  • NIC and driver. Native XDP support decides whether you get the fast path at all.
  • RSS and IRQ affinity. Queues and cores have to line up or one core saturates.
  • Program complexity. A heavier eBPF program costs more per packet. Keep the hot path lean.

I've covered the general shape of this in optimizing load balancing with eBPF, which is worth reading alongside Katran specifically.

Can you run Katran on Kubernetes as a DaemonSet

You can, but do it with clear eyes. Katran was not built as a Kubernetes-native controller, so there's no first-party operator that wires VIPs to Services and Endpoints for you. Running Katran as a DaemonSet means one instance per node handling the XDP data plane, plus glue you write or borrow to sync backend pools from the Kubernetes API and to announce VIPs over BGP.

The DaemonSet model fits because Katran wants to sit on every node that terminates edge traffic, with its own XDP program bound to that node's NIC. The gaps are real: pod lifecycle, health propagation, and BGP announcement all need something driving them. Some community projects and internal forks stitch this together, but there's no polished path you drop in unchanged.

If your goal is in-cluster east-west load balancing rather than an edge L4 plane, honestly reach for a Kubernetes-native eBPF dataplane first. Katran shines as a north-south edge balancer in front of the cluster, not as a Service proxy inside it. I go deeper on the cluster side in Cilium eBPF use cases.

What to check before you deploy Katran in production

Linux terminal showing network performance metrics and system monitoring output

Confirm three things before you build anything: kernel version, NIC driver XDP support, and your debugging toolchain. Katran needs a recent enough kernel for its eBPF features, so check what your distro ships and don't assume. Rather than trust a version number that goes stale, run uname -r and read the driver docs for your exact NIC to confirm native XDP, not just generic.

Verify driver mode after you load the program, not before. Attach it, then check with bpftool net show and ip link whether XDP landed in driver mode or fell back to generic. If it's generic, your throughput numbers will disappoint and you'll waste a day blaming the wrong layer. That tells you the driver, not Katran, is the problem.

Know your debugging path before the incident, not during it. bpftool prog and bpftool map show you what's loaded and what's in the maps. dmesg and the kernel ring buffer catch verifier rejections and driver complaints. For live packet tracing, bpftrace and tools like pwru follow a packet through the datapath so you can see where a flow actually dies. Read the output; it usually names the cause.

Where to find Katran's source and how active the project is

Katran lives on GitHub under Facebook's (Meta's) organization, and reading it is not optional if you plan to run it. The Katran source on GitHub is where the real documentation lives: the build steps, the BPF program, and the userspace control library that manages VIPs and backends. It is open source under a permissive license, which is the point. You can instrument it, extend it, and understand a failure instead of filing a ticket into a black box.

Set expectations on activity. This is infrastructure Meta runs, not a fast-moving consumer project, so commits come in bursts around real needs rather than daily churn. That's fine for a data plane. What matters is that the code is there, the abstractions are readable, and when something breaks you can trace the behavior back to a line instead of guessing.

How Katran compares to other load balancing options

Pick the tool to the layer. Katran is a Layer 4, kernel-bypass, north-south edge balancer. Most of what people compare it to solves a different problem.

OptionLayerWhere it fitsWhere it hurts
KatranL4 (XDP/eBPF)Edge, VIP-scale packet forwarding with DSRNo L7, not K8s-native, MTU and DSR planning
IPVSL4 (netfilter)Simpler in-kernel L4, smaller scaleLocks and stack cost cap peak pps
HAProxy / NGINXL7 proxyTLS termination, content routing, per-request logicFar higher per-packet CPU, not for raw pps
CiliumL3/L4/L7 (eBPF)Kubernetes-native dataplane and Service LBDifferent job; in-cluster, not an edge L4 plane
Cloud LBL4/L7 managedYou want zero operational depthCost, opacity, and provider lock-in

If you need SSL termination or route by URL, Katran is the wrong layer and HAProxy or NGINX is right. If you need in-cluster Kubernetes networking, Cilium is the better fit. If you want a managed box you never tune, a cloud load balancer is honest about that trade. Katran wins exactly when you need to move enormous packets-per-second at the edge, on your own hardware, with DSR, and you have the team to own it. For most shops that last condition is the real gate. If you're just trying to shave stack cost off an existing setup, start with reducing kernel overhead using eBPF before you reach for Katran.

FAQ

Does Katran do TLS termination or Layer 7 routing?
No, and that's by design. It reads IP and transport headers, picks a backend, and forwards. If you need to decrypt traffic or route by hostname or path, put an L7 proxy behind Katran and let each layer do its own job.

What breaks first when I deploy Katran?
Usually the return path or the MTU. DSR replies skip Katran entirely, so a reverse-path filter or a missing route silently eats responses. Right after that, the encapsulation header pushes packets over the MTU and full-size packets drop while small ones pass. Test both before you send real traffic.

Do I need a special NIC to run it well?
You need a NIC whose driver supports native XDP. Without it you fall back to generic XDP, which works but costs more per packet because the kernel has already touched the frame. Confirm the mode after loading with bpftool net show rather than trusting the spec sheet.

Is Katran overkill for a small service?
Almost always, yes. The operational depth only pays off at very high packets-per-second on hardware you control. For a handful of servers, IPVS or a plain L7 proxy gets you there with far less to maintain. Reach for Katran when you've actually outgrown those.

How does Katran keep connections alive when a backend leaves?
It uses consistent hashing based on Maglev, so removing one backend only moves the flows that mapped to it. Every other flow stays pinned to the same server. That's the whole reason it beats simple modulo hashing, where losing one server renumbers all of them and drops live connections.