Bonding Network Interfaces for Redundancy and Throughput on Linux
Configure Linux NIC bonding modes like active-backup and 802.3ad LACP for redundancy and bandwidth using systemd-networkd, nmcli, and a little AI help.
- #linux
- #networking
- #bonding
- #redundancy
I learned about bonding the hard way: a single Ethernet cable wiggled loose in a rack at 2 a.m., a database server dropped off the network, and a pager went off. One cable. One point of failure. The fix was embarrassingly cheap compared to the outage it caused, because the server already had a second NIC sitting completely idle. After that night I started treating link redundancy as table stakes for anything that mattered. This post is the walkthrough I wish I’d had: how Linux bonding actually works, the modes you’ll reach for in practice, and the exact commands to set it up and prove it survives a failure. I leaned on an AI assistant while drafting some of these configs, and I’ll be honest about where that helped and where it absolutely cannot be trusted.
What Bonding Actually Does
Bonding (sometimes called “teaming,” though that’s technically a different driver) aggregates multiple physical network interfaces into one logical interface, usually named bond0. To the rest of the system, bond0 looks like a single NIC with a single IP address. Underneath, the kernel’s bonding driver decides how traffic is distributed across the member interfaces, called “slaves,” and what happens when one of them dies.
The two things people want from bonding are almost always redundancy (survive a cable, port, or NIC failure) and throughput (use more than one link’s worth of bandwidth). Different modes optimize for different goals, and choosing wrong is the most common mistake I see. Bandwidth aggregation in particular has caveats that surprise people, which we’ll get to.
The Bonding Modes You’ll Actually Use
There are seven modes, but three cover the overwhelming majority of real deployments:
- mode 0 / balance-rr (round-robin): Packets are sent across slaves in strict rotation. This is the only mode that can give a single TCP connection more than one link’s bandwidth, but it causes out-of-order packet delivery, which TCP hates. Use it rarely and only with back-to-back links you control.
- mode 1 / active-backup: One slave is active; the rest sit on standby. If the active link fails, another takes over. No bandwidth gain, but it’s the simplest, most reliable redundancy and it needs zero switch configuration. This is my default when in doubt.
- mode 4 / 802.3ad (LACP): Dynamic link aggregation per the IEEE standard. Both the server and the switch negotiate a Link Aggregation Group. You get redundancy and aggregate throughput across multiple connections (not per-connection). This requires switch-side configuration, which is the part people forget.
There’s also mode 5 (balance-tlb) and mode 6 (balance-alb), which load-balance without switch support, but mode 4 is generally the better-supported choice in a managed-switch environment.
Pro Tip: If you can’t configure the switch, do not pick mode 4. A misconfigured 802.3ad bond where only one side speaks LACP often results in a flapping, half-broken link. When in doubt, active-backup is the mode that just works.
Loading the Bonding Module
On most modern distributions the bonding driver loads automatically when a bond is configured, but it’s worth knowing how to do it by hand for troubleshooting:
sudo modprobe bonding
lsmod | grep bonding
To make options persistent at the module level, you can drop a file in /etc/modprobe.d/, though I prefer to configure options per-bond in the network config rather than globally:
# /etc/modprobe.d/bonding.conf
# Only if you really want a module-level default; per-interface config is cleaner.
options bonding max_bonds=0
Setting max_bonds=0 prevents the module from auto-creating a bond0 you didn’t ask for, which keeps the network manager in full control of interface creation.
Configuring a Bond with systemd-networkd
If you’re on a server-oriented distro using systemd-networkd, this is the cleanest approach. You need a .netdev to define the bond device and .network files to bind the members and assign the address.
First, define the bond device in /etc/systemd/network/10-bond0.netdev:
[NetDev]
Name=bond0
Kind=bond
[Bond]
Mode=active-backup
MIIMonitorSec=100ms
PrimaryReslectPolicy=always
For an 802.3ad bond instead, the [Bond] block changes to set Mode=802.3ad and a transmit hash policy:
[Bond]
Mode=802.3ad
MIIMonitorSec=100ms
LACPTransmitRate=fast
TransmitHashPolicy=layer3+4
Next, enslave the physical interfaces. Create /etc/systemd/network/20-bond0-eno1.network:
[Match]
Name=eno1
[Network]
Bond=bond0
Repeat for eno2 in a 21-bond0-eno2.network file. Finally, configure the bond itself in /etc/systemd/network/30-bond0.network:
[Match]
Name=bond0
[Network]
DHCP=no
Address=192.168.10.20/24
Gateway=192.168.10.1
DNS=192.168.10.1
Apply it with sudo systemctl restart systemd-networkd. The MIIMonitorSec setting is the critical one for redundancy: it tells the driver how often to check link state via MII so it can fail over quickly. A value around 100ms is a sensible starting point.
Configuring a Bond with NetworkManager (nmcli)
On RHEL, Fedora, Ubuntu desktop, and anything NetworkManager-driven, nmcli is the path of least resistance. This is also the kind of repetitive, easy-to-typo sequence where an AI assistant earns its keep as a first-draft generator. Here’s an active-backup bond with miimon set:
sudo nmcli con add type bond ifname bond0 con-name bond0 \
bond.options "mode=active-backup,miimon=100"
sudo nmcli con add type ethernet ifname eno1 master bond0 \
con-name bond0-eno1
sudo nmcli con add type ethernet ifname eno2 master bond0 \
con-name bond0-eno2
sudo nmcli con mod bond0 ipv4.addresses 192.168.10.20/24
sudo nmcli con mod bond0 ipv4.gateway 192.168.10.1
sudo nmcli con mod bond0 ipv4.dns 192.168.10.1
sudo nmcli con mod bond0 ipv4.method manual
sudo nmcli con up bond0
For an LACP bond, the only real change is the options string:
sudo nmcli con mod bond0 bond.options \
"mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4"
That xmit_hash_policy deserves attention. In mode 4 (and the balance modes), it decides which slave a given flow uses. The default layer2 hashes on MAC addresses, which means all traffic to a single peer router pins to one link and you see no aggregate gain through a gateway. Switching to layer3+4 hashes on IP plus TCP/UDP port, spreading distinct connections across links far more evenly. This is the single setting that most often explains “why isn’t my LACP bond faster?”
This is roughly where I think about AI the way I think about a fast junior engineer. It will hand you a complete nmcli block in seconds, and it’ll usually be 90 percent right. But it will also confidently invent an option name or assume your switch is configured when it isn’t. You keep a human in the loop, you read every line before you run it, and you never give the assistant your production credentials or let it run commands against live infrastructure unattended. Draft locally, review, then apply yourself. If you want to turn that review habit into a workflow, our code review dashboard and the prompt patterns in the prompt workspace are built around exactly that “AI drafts, human approves” loop.
Verifying State and Forcing a Failover
The source of truth for a running bond is the kernel’s procfs file. Read it directly:
cat /proc/net/bonding/bond0
You’ll see the active mode, the MII polling interval, the currently active slave, and per-slave link status. For an 802.3ad bond it also reports the LACP aggregator ID and partner MAC, which is how you confirm the switch is actually negotiating with you. If the partner MAC is all zeros, the switch side isn’t speaking LACP and you’re effectively running on one link.
Now the important part: never trust a redundancy setup you haven’t tested. Down the active slave and watch traffic continue:
# Identify the active slave first
grep -A1 "Currently Active Slave" /proc/net/bonding/bond0
# In one terminal, keep a ping running to something across the bond
ping 192.168.10.1
# In another, take the active interface down
sudo ip link set eno1 down
In active-backup, you should see at most a packet or two drop before eno2 takes over. Re-reading /proc/net/bonding/bond0 will show the active slave has switched. Bring it back with sudo ip link set eno1 up. Do this during a maintenance window the first time, document the observed failover time, and you’ll sleep better.
Pro Tip: Test failover on both directions of the cable, not just at the server. Pulling the physical cable tests link detection; downing the interface with ip link set down tests the driver’s logic. They can fail differently, and the 2 a.m. version of you wants to know which.
A Note on the Switch Side
For mode 4, the switch ports must be configured into a matching Link Aggregation Group / port-channel with LACP enabled. The exact syntax is vendor-specific, but the principle is universal: both ends negotiate. If the server says 802.3ad and the switch ports are plain access ports, you’ll get a flapping mess. Active-backup, by contrast, asks nothing of the switch, which is exactly why it’s the safe default for hosts you don’t control the switch for.
Wrapping Up
Bonding turns a spare NIC and a second cable into genuine resilience, and in the LACP case, into more aggregate bandwidth. Reach for active-backup when you want bulletproof redundancy with no switch dependency, and 802.3ad when you control the switch and need throughput across many connections. Whichever you choose, prove it with /proc/net/bonding/bond0 and a real failover test. AI tools like Claude or Cursor are great for generating the boilerplate and catching typos, but the human stays accountable and the credentials stay out of the model. For more in this vein, browse the Linux admins category, grab a ready-made prompt from our prompts library, or pick up a curated set in the prompt packs store.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.