Keeping the directory up: mirror mode for write continuity, HAProxy and Nginx load balancers for reads, DNS round-robin, and failover patterns that keep authentication working when servers die.

A directory that authenticates the whole organization must never be down. Episode 26 turns the single-server setup into an available, scalable system: mirror mode for write continuity, HAProxy and Nginx for load balancing reads, DNS-based routing, and failover patterns. By the end, a dead server shouldn't be a user-visible event.
Availability has two measurable goals:
For LDAP specifically, three patterns combine:
The weak point of single-master is the writer: if the provider dies, writes stop until a consumer is promoted. Mirror mode (episode 13) fixes this with two writable servers. Combined with a load balancer in front, a single VIP (virtual IP) exposes both:
clients
|
[VIP: 10.0.0.10]
|
+----+----+
| |
ldap01 ldap02 (mirror mode)Both servers accept writes; the balancer distributes traffic; a dead node is simply removed. The caveat from episode 13 stands: mirror mode needs careful write-conflict discipline (via contextCSN), so use two writable nodes — not ten.
HAProxy is the classic TCP load balancer. It handles LDAP at the TCP layer (mode tcp), which works for plain LDAP, StartTLS, and LDAPS:
frontend ldap_in
bind *:389
mode tcp
default_backend ldap_servers
backend ldap_servers
mode tcp
balance roundrobin
option tcp-check
server ldap01 10.0.0.11:389 check inter 5s
server ldap02 10.0.0.12:389 check inter 5sFor LDAPS (port 636), the same but on port 636 with the servers on their LDAPS port. option tcp-check sends a health check so a dead node is dropped from rotation automatically.
For read-heavy workloads, a balance roundrobin across consumers is ideal. For write workloads, prefer balance first (or a single primary) to keep writes on one node and avoid conflict handling entirely.
Nginx's stream module balances LDAP at the TCP/UDP layer:
stream {
upstream ldap_backend {
server 10.0.0.11:389 max_fails=3 fail_timeout=30s;
server 10.0.0.12:389 max_fails=3 fail_timeout=30s;
}
server {
listen 389;
proxy_pass ldap_backend;
proxy_timeout 5m;
proxy_connect_timeout 2s;
}
}Nginx health-checks by TCP connection — it cannot verify LDAP replies the way tcp-check does in HAProxy. For production LDAP, HAProxy's tcp-check is the stronger choice.
The simplest approach: one hostname, multiple A records.
ldap.example.com. 300 IN A 10.0.0.11
ldap.example.com. 300 IN A 10.0.0.12DNS balancing spreads new connections but has no health awareness and stale-cache problems. It's a complement to a real load balancer, not a replacement.
A complete failover story:
tcp-check (or an LDAP bind check) removes the dead node in seconds.uri values fall back on their own when the first server fails; combine this with the balancer.contextCSN lag and node health so failures are detected before users notice.uri ldap://10.0.0.10
uri ldap://10.0.0.11
uri ldap://10.0.0.12Warning
Beware the split-brain case in mirror mode: if the network between ldap01 and ldap02 fails but both keep serving through the balancer, both accept writes and the directories diverge. Health checks must include replication lag (contextCSN), not just a TCP response, and the balancer should quarantine a node whose replication is stale.
In this episode 26 you made the directory highly available: mirror mode for write continuity, HAProxy with mode tcp and tcp-check, Nginx stream balancing, DNS round-robin with short TTLs, and a failover strategy combining balancer health checks, client-side retries, DNS fallback, and replication monitoring.
Key takeaways:
In the next episode, episode 27, we debug what goes wrong anyway: troubleshooting — reading the logs, common failures, and systematic diagnosis of binds, searches, replication, and performance.