Making the directory fast: mdb database tuning with olcDbMaxSize, olcDbCacheSize, and olcDbMaxReaders, index strategies, connection and operation limits, and operating system tuning.

The directory now serves authentication, mail, web apps, and replication. At some point, a surge in traffic will make it slow. Episode 25 is about performance: tuning the mdb database itself, choosing indexes that match real queries, and raising the connection and operating system limits so the server doesn't run out of resources under load.
The mdb backend is a memory-mapped key-value store — a database whose performance depends heavily on how much of it lives in memory and how much the file system must read. The core tuning values live in cn=config:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcDbMaxSize
olcDbMaxSize: 1073741824
-
replace: olcDbCacheSize
olcDbCacheSize: 10000
-
replace: olcDbMaxReaders
olcDbMaxReaders: 256| Parameter | What it does | Tuning rule |
|---|---|---|
olcDbMaxSize | maximum database file size in bytes | must exceed expected growth; resizing is a downtime operation |
olcDbCacheSize | number of page entries cached | larger = more memory, faster reads |
olcDbMaxReaders | maximum concurrent readers | raise when you see reader exhaustion |
olcDbMaxIDL | max index list length | limits how many index entries a single search may scan |
olcDbMaxSize is the most common trap: the default is often 10 MB in packaged builds, and when data reaches it, writes fail. The 1 GB value (1073741824) is a reasonable production start — but make it proportional to the actual dataset, and plan for growth because changing it later requires stopping the server.
cn=Monitor statistics (e.g. monitorDatabaseRead versus monitorDatabaseWrite) and raise olcDbCacheSize until the read pressure drops.olcDbMaxReaders, new searches fail with MDB_READERS_FULL. Raise the limit, but remember each reader consumes some memory; balance with the number of expected concurrent connections.ldapadd of thousands of entries will queue. This is inherent to mdb — plan write bursts accordingly.From episode 14, indexes are the biggest lever on search speed. The tuning version:
(uid=...) needs uid eq; returning mail as a result attribute does not need an index.sub only where wildcards are used — (cn=*bang*) filters need sub; (uid=budi) does not. Unused sub indexes waste disk and write time.entryCSN eq and entryUUID eq keep syncrepl fast; an unindexed contextCSN lookup is a full scan on every sync.sub/approx indexes, database growth outpaces data growth. Audit indexes every release cycle against real query patterns.slapd has a set of limits to keep one client from starving the server:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcLimits
olcLimits: dn.exact="cn=admin,dc=example,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
olcLimits: dn.exact="cn=replicator,dc=example,dc=com" time.soft=3600 time.hard=3600 size.soft=unlimited size.hard=unlimitedsize limits — maximum number of entries a single search returns.time limits — maximum seconds a search may run.olcSizeLimit/olcTimeLimit — global defaults applied when a limit isn't explicit.olcSizeLimit: 500
olcTimeLimit: 60Assign generous limits to trusted DNs (admin, replication) and tight limits to anonymous and application binds. This prevents a single runaway query from blocking every other client.
The kernel and file system participate in performance too:
nofile for the slapd user.olcDbMaxSize if the working set spills to swap.somaxconn for the accept queue under many simultaneous connections.ulimit -n
systemctl show slapd -p LimitNOFILETuning without measurement is guesswork. Measure before and after:
ldapsearch with time — a baseline for single queries.ldapbench / benchrfc — simple throughput tools in the OpenLDAP source tree.cn=Monitor — connection, operation, and database counters over time.slapd-metrics / Prometheus — from episode 18, continuous dashboards show regression after a change.time ldapsearch -x -D cn=admin,dc=example,dc=com -W \
-b ou=people,dc=example,dc=com "(mail=*)"Track three numbers on every change: search latency, throughput (ops/sec), and write latency. A tuning change that improves one while wrecking another is not an improvement.
Tip
Change one parameter at a time. If you raise olcDbCacheSize, cache and olcDbMaxReaders together, you won't know which one did the work — or which one caused a regression. Small, measured steps beat big blind jumps.
In this episode 25 you tuned OpenLDAP performance: mdb parameters olcDbMaxSize, olcDbCacheSize, olcDbMaxReaders, and olcDbMaxIDL; cache and reader behavior including the single-writer model; index strategies based on real filters; olcLimits and global size/time limits; OS tuning for descriptors, RAM, and storage; and benchmarking with time, cn=Monitor, and Prometheus.
Key takeaways:
olcDbMaxSize is the first thing to check — running out is a write outage.In the next episode, episode 26, we make the tuned system survive failures: HA & load balancing — mirror mode, HAProxy, Nginx, DNS load balancing, and failover patterns for the directory.