Library / SDK
facebook/dhcplb avatar
facebook/dhcplb

dhcplb: Facebook's load balancing DHCP relayer

dhcplb is Facebook's implementation of a load balancer for DHCP.

1,063 stars85 forksGoMIT

At a glance

What is it?
dhcplb is a Go implementation of a DHCPv4 and DHCPv6 relayer that spreads requests across a pool of servers, plus a server mode that talks to your own backends. It exists because anycast with ECMP produced badly skewed DHCP load, and it only works with unicast traffic from a relayer, which is the single constraint that decides whether you can use it.
Who is it for?
Adopt dhcplb if you run a fleet of servers behind a relay architecture and anycast plus ECMP is sending a disproportionate share of DHCP traffic to a single node, and if you can accept the unicast-only constraint and the Go 1.19 baseline. Do not adopt it for a small network where one DHCP server is enough, or if your clients send broadcast DISCOVERY or multicast SOLICIT directly, which the code does not handle.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 65 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two modes, one process

dhcplb is Facebook's implementation of two things: a DHCP v4 and v6 relayer with load balancing capabilities, and a DHCP v4 and v6 server framework.

The relayer is the part that spreads work. DHCP traffic arrives at a load balancer, and instead of answering it, the balancer forwards it to a pool of real servers so that the load is spread rather than concentrated on one node.

The server framework is the other half, added later, and the README is candid about why. Facebook needed a server implementation that would allow both a multithreaded design, to avoid blocking requests when doing backend calls, and an interface to be able to call other services for getting the IP assignment and the boot file url. The framing of the server mode is that dhcplb does not own the answer, it asks a backend service for it.

The implementation is built on the @insomniacslk dhcp library for the protocol handling, and the module declaration in go.mod pins that dependency to a specific commit along with fsnotify, glog, an LRU cache from hashicorp, testify and golang.org/x/time. The Go version declared is 1.19.

The repository is MIT licensed in its metadata, the last push was on 2026-08-19, and there are no GitHub releases, so the code is built from source rather than fetched as a tagged artefact. The README's own licence section says BSD License and points at the LICENSE file, so the two statements in the repository do not agree and the file is the one to read.

The problem Anycast and ECMP could not solve

The README explains the origin in a paragraph that is worth reading in full, because it defines the problem in terms of a measurement rather than a generalisation.

Facebook uses DHCP to provide network configuration to bare-metal machines at the provisioning phase, and to assign IPs to out-of-band interfaces. dhcplb was created because the previous infrastructure surrounding DHCP led to very unbalanced load across the DHCP servers in a region when simply using Anycast plus ECMP alone. The example given is stark: one server out of ten would receive more than 65% of the requests.

That failure mode is worth understanding. Anycast plus ECMP hashes the flow to a set of anycast addresses and lets the network pick a path, which is a good design for stateless traffic. DHCP is not stateless traffic in that sense, because the response has to come back to the client and the client will only accept it in the context of the broadcast it sent, which constrains which node can serve it. The result is a distribution that looks fine on paper and concentrates badly in practice.

The README also records why an off-the-shelf component was not used, and the answer is specific: all the relayer implementations available on the internet lack the load balancing functionality. It then lists what owning the code buys, namely the ability to perform A/B testing on new builds of the DHCP server, to implement an override mechanism, and to implement anything additional that is needed.

The history is in the repository too. The project started in April 2016 during a three day hackathon in the Dublin office, where the hackathon project proved the feasibility of the tool, and in June it was joined by Vinnie Magro for a three month internship in which he worked with two production engineers to turn the hack into a production ready system. The README states that Facebook currently uses it in production, deployed at global scale across all of its data centers.

The two layer packet path

The deployment model is what makes the tool work, and it is drawn in the README as an ASCII diagram.

In v4, dhcplb relays messages that come from other relayers, in the production network the rack switches, and the response from the server is relayed back to those rack switches:

text
dhcp client <---> rsw relayer ---> dhcplb (relay) ---> dhcplb (server)
                      ^                                      |
                      |                                      |
                      +--------------------------------------+

In DHCPv6, responses from the dhcp server traverse the load balancer, so the return path goes through the balancer rather than straight back to the client.

Above that, the deployment has two layers. The top of rack switches run DHCP relayers whose job is to relay the broadcast DHCP traffic, the DISCOVERY and SOLICIT messages originating within their racks, to anycast VIPs, one for DHCPv4 and one for DHCPv6. On a Cisco switch the configuration looks like this:

text
ip helper-address 10.127.255.67
ipv6 dhcp relay destination 2401:db00:eef0:a67::

The dhcplb instances listen on those VIPs, deployed as containerised Tupperware instances in every region, and their job is to balance the relayed traffic among the actual dhcplb servers distributed across clusters in the same region.

The reason for two layers is stated plainly: having two layers allows A/B testing changes of the server implementation. That is the same motivation as the A/B testing ability in the earlier section, applied to a different level of the system. One layer to reach the region, one layer to choose the server.

Three configuration files, one of them per MAC address

The configuration is split across three files, and the split maps onto the three things you might want to change.

The json config file holds the main configuration for the server, explained in the Getting Started section of the documentation. The host lists file contains a list of dhcp servers, one per line, and those are the servers dhcplb will balance across. The overrides file contains per mac overrides.

All three are visible in the repository, which is convenient. There is a config.json at the root, a hosts-v4.txt and a hosts-v6.txt for the two address families, and an overrides.json.

The host list is the simplest of the three and it is the one that determines the balancing. It is a flat list of servers, one per line, and dhcplb balances the incoming requests across them. There is no weighting described in the README, so the list describes a pool rather than a policy.

The overrides file is the one that solves a specific operational problem, because an override is per mac. A machine that must always get the same address, or that must be served by a particular server, can be pinned by its hardware address rather than left to the balance. The README also lists an override mechanism as one of the things owning the code makes possible.

The documentation has a separate page for integration, Extending DHCPLB, which is where the backend interface lives. The source tree shows how that is wired: config_provider.go is the configuration side, and glog_logger.go is the logging adapter, both sitting next to main.go and the lib/ directory. The go.mod dependencies give a hint about the mechanics, since fsnotify is a file watcher, which suggests that a changing host list or overrides file can be picked up without a restart.

Installing and running it in a terminal

The installation is the Go toolchain's own installer, and the README gives the command:

bash
go install github.com/facebook/dhcplb@latest

That places the binary at $GOPATH/bin/dhcplb. If you would rather work from a clone, the README gives the sequence, which uses the GOPATH source layout rather than modules:

bash
mkdir -p $GOPATH/src/github.com/facebook
cd $_
git clone https://github.com/facebook/dhcplb
go install github.com/facebook/dhcplb

The unit tests live in the lib directory and are run with the standard tool:

bash
cd $GOPATH/src/github.com/facebook/dhcplb/lib
go test

And the tool can be started straight away after compilation. The README says dhcplb can be run out of the box after compilation, and the immediate command is:

bash
sudo dhcplb -config config.json -version 6

Two flags, and both are doing real work. The config flag points at the JSON configuration file, and the version flag selects the address family, so this invocation starts the relay in v6 mode using the default configuration. It needs sudo because it binds to the privileged DHCP ports.

The remaining documentation is where a real deployment starts. The Getting Started page covers the configuration, and the Extending DHCPLB page is the one to read if you intend to plug in your own backend service for the IP assignment and the boot file url, since that interface is the reason the server mode exists.

The vagrant lab reproduces the packet path

For a network daemon, a test environment that does not resemble production is nearly useless, and the README is explicit that the project ships one that does.

The virtual lab is brought up with vagrant and replicates the production environment, and you can spawn virtual machines containing the various components. The list is: N instances of ISC dhcpd, which are the real servers being balanced across; an instance of dhcplb; an instance of dhcrelay, simulating a top of rack switch; and a virtual machine where you can run dhclient or ISC perfdhcp to generate traffic.

That is the whole path from the packet path diagram, in executable form. dhcrelay stands in for the rack switch, dhcplb balances, ISC dhcpd serves, and dhclient or perfdhcp is the client. All of it is managed by vagrant and chef-solo cookbooks, and there is more in the vagrant directory with its own README.

The inclusion of ISC dhcpd in the lab is the clearest signal about the intended relationship between the two projects. The lab lets you test the balancing layer in front of a server you already have.

The other server implementation the README names is ISC KEA, and it appears in the story of why server mode was added. A single threaded application queuing up packets while doing backend calls to another service was not scaling well, which is the specific problem the multithreaded design in dhcplb's own server mode addresses.

The broadcast gap and the Go baseline

Two constraints decide whether dhcplb fits your network, and both are stated in the README rather than left to be discovered.

The first is the traffic model. Both modes currently only support handling messages sent by a relayer which is unicast traffic, and they do not support broadcast v4 and multicast v6 requests. The TODO section repeats it in the protocol terms: dhcplb does not support relaying or responding to broadcasted DHCPv4 DISCOVERY packets or DHCPv6 SOLICIT packets sent to the ff02::1:2 multicast address. The project says it does not need this in its production environment but that adding the support should be trivial.

Whether that is trivial for you depends on your network. If your clients reach the balancer through a relay, as in the rack switch configuration shown above, the traffic arrives unicast and everything works. If your clients broadcast onto the segment and expect a server to answer, this is the wrong tool, and the gap is in the protocol path rather than in a configuration detail. The tracking of open enhancements is done through GitHub issues with an enhancement label.

The second constraint is the toolchain. The module declares go 1.19, and the README's own build instructions use the GOPATH source layout with a git clone into $GOPATH/src, which is a pre-modules convention. Both of those are still workable, but they tell you the project has not moved to the current idioms, and a team that has standardised on modules with a vendored toolchain will find the documented clone path slightly awkward.

The project is not archived and the last push was on 2026-08-19, so the code is being touched, and the README closes with the note that pull requests are welcome.

Editorial conclusion

Adopt dhcplb if you run a fleet of servers behind a relay architecture and anycast plus ECMP is sending a disproportionate share of DHCP traffic to a single node, and if you can accept the unicast-only constraint and the Go 1.19 baseline. Do not adopt it for a small network where one DHCP server is enough, or if your clients send broadcast DISCOVERY or multicast SOLICIT directly, which the code does not handle. Verify first that your traffic reaches dhcplb through a relayer, that the hosts list matches the servers you want to balance across, and that the per MAC overrides file matches the devices you need to pin.

Frequently asked questions

How do I install dhcplb?

Run go install github.com/facebook/dhcplb@latest, which puts the binary in $GOPATH/bin/dhcplb. The README also gives a clone based route that creates $GOPATH/src/github.com/facebook, clones the repository there and runs go install.

How do I start dhcplb in relay mode?

The README gives sudo dhcplb -config config.json -version 6, which starts the relay in v6 mode using the default configuration. The config flag points at the JSON configuration file and the version flag selects the address family.

Does dhcplb handle broadcast or multicast DHCP requests?

No. Both modes only support messages sent by a relayer, which is unicast traffic, and the project does not support relaying or responding to broadcasted DHCPv4 DISCOVERY packets or DHCPv6 SOLICIT packets sent to the ff02::1:2 multicast address.

What files does dhcplb need to be configured?

Three: a json config file with the main configuration, a host lists file containing the dhcp servers to balance across, one per line, and an overrides file containing per mac overrides. The repository ships config.json, hosts-v4.txt, hosts-v6.txt and overrides.json.

Official sources

  1. facebook/dhcplb on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/facebook-dhcplb.svg)](https://hysenlabs.com/projects/facebook-dhcplb)

Was this useful?