Configure LDAP Threads and Connections in 389 Directory Server

Tune 389 Directory Server worker threads, listener threads, per-connection limits, idle timeouts, and file descriptors with dsconf and monitor output.

Published

Updated

Read time 10 min read

Reviewed byDeepak Prasad

389 Directory Server worker threads connection listeners file descriptors and monitor counters

When many clients connect at once, worker threads, listener threads, and file descriptors determine whether operations queue or fail. This guide covers thread and connection tuning in 389 Directory Server.

Before you start:

IMPORTANT
This guide covers nsslapd-threadnumber, nsslapd-numlisteners, nsslapd-maxthreadsperconn, idle and I/O timeouts, and file descriptors. It does not configure search limits, LMDB cache, or host-level TCP stack tuning.

Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.


Understand worker and connection resources

Thread or limit Attribute Purpose
Worker threads nsslapd-threadnumber Execute LDAP operations (-1 = auto-tune from CPU count; takes effect at startup after restart)
Listener threads nsslapd-numlisteners Monitor established client connections (valid range 14; restart required)
Per-connection workers nsslapd-maxthreadsperconn Cap simultaneous asynchronous operations from one connection (1 through active worker count)
Idle timeout nsslapd-idletimeout / nsIdleTimeout Close unused connections after N seconds (0 disables automatic idle disconnect)
I/O block timeout nsslapd-ioblocktimeout Milliseconds to wait on blocked network I/O (lab default 10000 = 10 seconds)
File descriptors nsslapd-maxdescriptors / nsslapd-reservedescriptors Total descriptor ceiling and reserved pool for non-client use
Socket backlog nsslapd-listen-backlog-size Pending socket queue for incoming connections during bursts

nsslapd-numlisteners configures threads that monitor established client connections. nsslapd-listen-backlog-size controls the pending socket queue for incoming connections. Backlog tuning does not increase the number of threads monitoring established connections.

Increasing worker threads cannot fix unindexed searches, slow storage, lock contention, or client-side delays. Too many threads can add scheduling overhead without raising throughput.


Check current thread and connection settings

bash
dsconf ldap1 config get nsslapd-threadnumber nsslapd-numlisteners nsslapd-maxthreadsperconn nsslapd-maxdescriptors nsslapd-reservedescriptors nsslapd-listen-backlog-size nsslapd-idletimeout nsslapd-ioblocktimeout
output
nsslapd-threadnumber: 16
nsslapd-numlisteners: 1
nsslapd-maxthreadsperconn: 5
nsslapd-maxdescriptors: 524288
nsslapd-reservedescriptors: 65
nsslapd-listen-backlog-size: 128
nsslapd-idletimeout: 3600
nsslapd-ioblocktimeout: 10000

The lab baseline is sixteen worker threads, one listener, five operations per connection, and 524288 max descriptors with 65 reserved.

The configured descriptor allowance for TCP clients is approximately nsslapd-maxdescriptors minus nsslapd-reservedescriptors, which is 524223 in this lab. This is not a guaranteed simultaneous-client count. The live dtablesize monitor value reports the Directory Server connection-table size; in this lab it is 63936, which is a lower practical connection-slot boundary. Monitor dtablesize, currentconnections, the operating-system descriptor limit, and the error log together. Changes to either descriptor setting require a restart.


Tune worker threads

Prefer automatic tuning unless repeatable load tests justify a fixed count:

bash
dsconf ldap1 config replace nsslapd-threadnumber=-1
output
Successfully replaced value(s) for 'nsslapd-threadnumber': '-1'

nsslapd-threadnumber defines the worker threads created at startup. Restart so auto-tuning takes effect:

bash
dsctl ldap1 restart

Read the attribute after restart:

bash
dsconf ldap1 config get nsslapd-threadnumber
output
nsslapd-threadnumber: 16

Setting -1 enables auto-tuning, but config get displays the calculated active thread count. On this lab host, which falls in the 1–16 CPU range, the value is 16. That displayed number does not mean the configuration has become a fixed manual value.

Automatic behaviour on current RHDS guidance:

text
1–16 CPU threads:
  16 Directory Server worker threads

17–512 CPU threads:
  One worker per CPU thread

More than 512 CPU threads:
  Maximum 512 worker threads

Return to a fixed pool only when measurement requires it. The fixed value takes effect after restart:

bash
dsconf ldap1 config replace nsslapd-threadnumber=16
bash
dsctl ldap1 restart

Auto-tuning should remain the normal recommended end state unless repeatable load testing justifies a fixed value.


Tune listener threads and per-connection limits

Connection listener threads

bash
dsconf ldap1 config get nsslapd-numlisteners
output
nsslapd-numlisteners: 1

The documented default is 1 and the valid range is 1 through 4. Increase listener threads only when testing with many established connections shows that one listener cannot service connection activity efficiently:

bash
dsconf ldap1 config replace nsslapd-numlisteners=4

Restart after changing listener count:

bash
dsctl ldap1 restart

Pending connection bursts during accept are controlled separately by nsslapd-listen-backlog-size, not by adding listener threads.

Per-connection worker limit

bash
dsconf ldap1 config get nsslapd-maxthreadsperconn
output
nsslapd-maxthreadsperconn: 5

This limit matters when one LDAP connection submits several asynchronous operations. Search the access log for per-connection pressure before raising the cap:

bash
grep -E 'notes=.*(N|B)' /var/log/dirsrv/slapd-ldap1/access
output
conn=66 op=973 RESULT err=0 tag=101 nentries=2 etime=0.000571769 notes=N details="Not synchronous operation"

notes=N identifies asynchronous operations that may consume multiple workers. notes=B identifies an operation that is delaying other incoming operations on the same connection.

Raise the limit only when monitoring supports it. The valid range is 1 through the active worker-thread count:

bash
dsconf ldap1 config replace nsslapd-maxthreadsperconn=10
output
Successfully replaced value(s) for 'nsslapd-maxthreadsperconn': '10'

Verify the change:

bash
dsconf ldap1 config get nsslapd-maxthreadsperconn
output
nsslapd-maxthreadsperconn: 10

Monitor while the application exercises concurrent operations on one connection:

bash
dsconf ldap1 monitor server

Watch maxthreadsperconnhits and currentconnectionsatmaxthreads during the test. Increasing this value reallocates more of the global worker pool to a single connection. It can help a legitimate asynchronous client but can also let one connection consume a disproportionate number of workers.

Restore the lab baseline after testing:

bash
dsconf ldap1 config replace nsslapd-maxthreadsperconn=5

Do not raise nsslapd-maxthreadsperconn merely because an application opens many separate connections.


Configure idle, I/O, and connection limits

Global idle timeout

Close idle connections after ten minutes:

bash
dsconf ldap1 config replace nsslapd-idletimeout=600
output
Successfully replaced value(s) for 'nsslapd-idletimeout': '600'

nsslapd-idletimeout: 0 disables automatic idle disconnection. A value that is too low can interrupt long-lived application pools and replication initialization.

Per-user idle timeout

Service or replication accounts can carry a longer idle timeout without weakening the global policy. With the global value at 600 seconds above, grant reporting-app thirty minutes. Save application-idle-timeout.ldif:

ldif
dn: uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com
changetype: modify
replace: nsIdleTimeout
nsIdleTimeout: 1800
bash
ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f application-idle-timeout.ldif
output
modifying entry "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com"
bash
ldapsearch -x -H ldap://ldap1.example.com:389 \
  -D "cn=Directory Manager" -W \
  -b "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com" \
  -s base "(objectClass=*)" nsIdleTimeout
output
nsIdleTimeout: 1800

Per-user nsIdleTimeout overrides nsslapd-idletimeout for that bind DN. Selected accounts can also receive a tighter timeout when a stricter per-application limit is required.

Blocked I/O timeout

nsslapd-ioblocktimeout closes a connection when the client makes no progress during a read or write. The lab default 10000 is ten seconds. Raising the value allows slow clients longer to recover, but also retains blocked connections and their descriptors for longer.

bash
dsconf ldap1 config replace nsslapd-ioblocktimeout=180000
output
Successfully replaced value(s) for 'nsslapd-ioblocktimeout': '180000'

180000 milliseconds is 180 seconds. Use such a high value only when legitimate slow clients are being disconnected by the default ten-second timeout. Confirm the unit and supported range in the configuration reference for the installed release before selecting a production value.

File descriptors

bash
dsconf ldap1 config get nsslapd-maxdescriptors nsslapd-reservedescriptors

Check the systemd unit limit before raising Directory Server descriptors:

bash
systemctl show dirsrv@ldap1 -p LimitNOFILE
output
LimitNOFILE=524288

The service limit matches nsslapd-maxdescriptors: 524288 on the lab host. nsslapd-reservedescriptors protects descriptors needed for indexes, databases, logs, replication, chaining, and other non-client activity. Do not set nsslapd-maxdescriptors above the operating-system limit.

Socket backlog

bash
dsconf ldap1 config replace nsslapd-listen-backlog-size=256

Use backlog tuning only when connection bursts fill the pending socket queue. It does not add listener threads for established connections.


Monitor connections, threads, and queued operations

bash
dsconf ldap1 monitor server

Sample output (trimmed):

output
threads: 18
currentconnections: 1
totalconnections: 2
currentconnectionsatmaxthreads: 0
maxthreadsperconnhits: 0
dtablesize: 63936
readwaiters: 0
opsinitiated: 12
opscompleted: 11

currentconnections is the open connection count right now. maxthreadsperconnhits shows how often clients exceeded nsslapd-maxthreadsperconn. dtablesize reports the connection-table size. The supported operation counters are opsinitiated and opscompleted.

threads reports the current number of active request-handling threads. Red Hat documents that internal tasks such as replication can create additional threads beyond the nsslapd-threadnumber pool. On this lab host config get shows 16 configured workers while monitor reports threads: 18. Use nsslapd-threadnumber for the startup worker pool and threads for the live count.

Also read the monitor LDAP entry:

bash
ldapsearch -x -H ldap://ldap1.example.com:389 \
  -D "cn=Directory Manager" -W \
  -b "cn=monitor" -s base "(objectClass=*)" \
  currentconnections totalconnections \
  currentconnectionsatmaxthreads maxthreadsperconnhits \
  dtablesize readwaiters threads opsinitiated opscompleted
output
currentconnections: 1
totalconnections: 3
currentconnectionsatmaxthreads: 0
maxthreadsperconnhits: 0
dtablesize: 63936
readwaiters: 0
threads: 18
opsinitiated: 15
opscompleted: 14

Watch these signals after thread or connection changes:

  • currentconnections approaching the usable client-descriptor capacity, while dtablesize and the error log indicate low descriptor headroom
  • currentconnectionsatmaxthreads remaining above zero
  • maxthreadsperconnhits increasing on LDAP connection pools
  • readwaiters rising because of slow clients or networks
  • Access-log wtime increasing because operations are waiting in the work queue

Red Hat defines wtime as the period an operation waits in the work queue before a worker thread accepts it. When the server runs out of descriptors, the error log can report Not listening for new connections -- too many fds open.

dsconf ldap1 monitor ldbm complements server-wide monitoring when database load shifts after connection tuning.


Restore lab baseline after testing

The examples above change production-impacting values. Restore the lab defaults and restart when tuning exercises finish:

bash
dsconf ldap1 config replace nsslapd-threadnumber=-1
dsconf ldap1 config replace nsslapd-numlisteners=1
dsconf ldap1 config replace nsslapd-maxthreadsperconn=5
dsconf ldap1 config replace nsslapd-idletimeout=3600
dsconf ldap1 config replace nsslapd-ioblocktimeout=10000
dsconf ldap1 config replace nsslapd-listen-backlog-size=128
bash
dsctl ldap1 restart

Remove the per-user idle override when the exercise used application-idle-timeout.ldif. Save remove-application-idle-timeout.ldif:

ldif
dn: uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com
changetype: modify
delete: nsIdleTimeout
bash
ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f remove-application-idle-timeout.ldif
output
modifying entry "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com"

Verify the restored configuration:

bash
dsconf ldap1 config get nsslapd-threadnumber nsslapd-numlisteners nsslapd-maxthreadsperconn nsslapd-idletimeout nsslapd-ioblocktimeout nsslapd-listen-backlog-size
output
nsslapd-threadnumber: 16
nsslapd-numlisteners: 1
nsslapd-maxthreadsperconn: 5
nsslapd-idletimeout: 3600
nsslapd-ioblocktimeout: 10000
nsslapd-listen-backlog-size: 128

After restart with nsslapd-threadnumber=-1, config get may still display the calculated thread count such as 16. That is expected auto-tuning behaviour, not a fixed manual setting.


Troubleshoot thread and connection problems

Symptom Likely cause Fix
maxthreadsperconnhits climbing Too many concurrent ops per connection Raise nsslapd-maxthreadsperconn within the worker count or spread load across connections
notes=N or notes=B in access logs Asynchronous or blocking operations on one connection Review client behaviour before raising per-connection limits
Connections dropped after idle periods nsslapd-idletimeout or load-balancer timeout Align server, firewall, and client pool keepalive settings; consider per-user nsIdleTimeout
Bind failures under load Descriptor limit mismatch Align nsslapd-maxdescriptors with LimitNOFILE; check usable capacity minus reserved descriptors
Not listening for new connections -- too many fds open Descriptor exhaustion Review dtablesize, currentconnections, and reserved descriptors
Thread count unchanged after -1 Auto-tune displays calculated value Read monitor server threads and CPU count
Increasing threads does not help Bottleneck is indexing, I/O, or locks Restore automatic tuning; fix search and storage problems first

What's next

After you complete this guide, continue with:

Summary

  1. Prefer nsslapd-threadnumber=-1 unless load tests justify a fixed count after restart.
  2. Listener threads default to 1; raise nsslapd-numlisteners only when many established connections show response-time degradation.
  3. Usable client descriptor capacity is approximately nsslapd-maxdescriptors minus nsslapd-reservedescriptors.
  4. Monitor currentconnectionsatmaxthreads, maxthreadsperconnhits, readwaiters, dtablesize, and access-log wtime after every change.
  5. Fix expensive searches through search limits and indexes before adding workers.

References


Frequently Asked Questions

1. What happens when nsslapd-threadnumber is set to -1?

A value of -1 enables automatic thread tuning based on available CPUs. After restart, config get may still display a calculated positive number such as 16 on a 16-core host. That number is the active thread count, not a fixed manual setting.

2. Should I raise nsslapd-numlisteners on every server?

No. The documented default is 1. Increase listener threads only when a large number of established client connections causes measured response-time degradation. Pending connection bursts are controlled separately by nsslapd-listen-backlog-size.

3. How do worker threads differ from listener threads?

Worker threads execute LDAP operations. Listener threads monitor established client connections and hand work to the pool. They solve different problems and are tuned separately.

4. What should nsslapd-maxdescriptors be relative to the operating system?

nsslapd-maxdescriptors must stay at or below the process file-descriptor limit from systemd LimitNOFILE. Usable client capacity is approximately nsslapd-maxdescriptors minus nsslapd-reservedescriptors. Raising the Directory Server value above the OS limit does not create additional usable descriptors.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …