RTFM · Load balancing
Load balancing on Saphira
Two ways to spread work across several servers: HAProxy in user space, and LVS with ldirectord inside the kernel; plus one shared idea that makes both trustworthy: health checks. This page is the map; the pages below are the territory.
The problem in one picture
Imagine a bank with one teller window. A queue forms, one slow customer blocks everyone, and when the teller goes to lunch the whole bank stops. Load balancing is opening more windows and hiring a floor manager who decides, customer by customer, which window is free, and who quietly stops sending people to a window whose teller has stepped away.
The servers behind the balancer are called real servers or backends. The address the world connects to is the virtual service. The floor manager's daily question, "is this teller actually working right now?", is the health check, and it is the difference between a load balancer and a round-robin DNS entry pretending to be one.
Two directors, two layers
Saphira ships two genuinely different load balancers, and choosing between them is choosing where the work happens:
| HAProxy | LVS + ldirectord | |
|---|---|---|
| Where it runs | User space, one process per service | Kernel (IPVS) with a small control daemon |
| Layer | Layer 4 (TCP) and Layer 7 (HTTP: Host, path, cookies, headers) | Layer 4 (address and port only) |
| Speaks protocols | Anything over TCP, and understands HTTP deeply | Any IP protocol, TCP, UDP, ESP, GRE, without understanding them |
| Throughput model | Every connection is proxied: two sockets per client | Packets are forwarded at kernel speed; backends can reply directly (DR); near wire rate |
| TLS | Can terminate, inspect, or pass through | Never sees inside the stream; passthrough by nature |
| IPv6 story | Mature on both sides | First-class on Saphira: our patched ldirectord parses bracketed IPv6 services and reals exactly |
| Typical Saphira use | Publishing mail and web names on one edge address | Balancing heavy or unusual services: databases, VoIP, DICOM, UDP, non-HTTP protocols |
The honest summary: if the decision needs to read HTTP, use HAProxy. If the service is not HTTP at all, or the traffic is heavy enough that copying every byte twice would hurt, use LVS. Many sites run both: LVS balancing the flood, HAProxy publishing the names.
Health checks: the part that matters
A balancer that spreads traffic across one live server and one dead one is worse than no balancer: half of your customers get a busy signal. Health checks are periodic probes the balancer runs against each real server, and the rule is simple; a server that fails its probe receives no new customers until it passes again.
Saphira supports two families of checks, and the distinction runs through the rest of this chapter:
- Internal checks are built into the balancer itself. HAProxy can connect to a TCP port or issue an HTTP request; ldirectord can connect, ping, or run a protocol conversation. Zero extra moving parts, but the vocabulary is limited to what the balancer's authors imagined.
- External checks are small programs the balancer executes; the program's exit code is the verdict. Any protocol anyone can write a script for becomes a health check; that is what the saphira-lb-healthchecks and saphira-lb-medical-healthchecks packages provide: DICOM, HL7, FHIR, DNS, RADIUS, SIP, Redis, raw UDP, and friends.
Both directors accept the same external-check interface: the five standard arguments ($1–$5: virtual service, virtual port, real address, real port, virtual source) that ldirectord and HAProxy pass to any external check, and exit 0 for healthy. A check written once works unchanged under either director.
Which one do I need?
| You need to… | Use |
|---|---|
| Publish several HTTP(S) names from one address | HAProxy (Layer 7 routing by Host header) |
| Balance SMTP/IMAP/POP3 with TLS passthrough | HAProxy in TCP mode, or LVS for pure scale |
| Balance a database, LDAP, SIP, RADIUS or any non-HTTP protocol | LVS + ldirectord with the matching external check |
| Balance UDP or raw IP protocols (GRE, ESP) | LVS + ldirectord: HAProxy cannot |
| Health-check a PACS, modality, HIS or FHIR server | Either director + the saphira-lb-medical-healthchecks package |
| Line-rate forwarding where backend replies can bypass the director | LVS in Direct Routing mode |
Where to go next
-
1. Read the director pages
HAProxy if you are publishing names; LVS/ldirectord if you are balancing protocols or flood traffic.
-
2. Pick your check family
Internal checks for simple up/down, external checks when the promise is "this service actually works".
-
3. Wire one check, prove it by hand, then automate
Every check page shows the manual command first; if it does not exit 0 by hand, it will not pass under a balancer either.
Prove it works: You can name the pieces
You can point at a diagram and say: that is the virtual service, those are the real servers, this is the check, and this is what happens to a customer when the check fails.
Questions people actually ask
Do I need both balancers?
Do the healthchecks work with both?
Will a health check ever touch real patient data?
Did we miss something?
If this page left something unanswered, found an error, or there is another subject you would like documented, tell us. Saphira’s documentation grows from real problems people need to solve.
Send feedback or request a new section →
Prefer not to do it yourself?
Everything needed to do the work yourself is documented here and remains free; we charge for human time, not for withholding knowledge. Sometimes the missing resource is simply time. The same people who build Saphira can provide paid professional help with implementation, migration, troubleshooting and administration.