A single broad LDAP search can walk thousands of candidate entries and return more data than an application can handle. Directory Server enforces size, time, look-through, and ID-list limits so one client cannot exhaust the instance.
This guide covers search resource limits in 389 Directory Server:
- Global instance limits in
cn=config - Global LDBM database plug-in limits for look-through and ID-list behaviour
- Per-user operational overrides for application bind accounts
- Paged and range search limits
- Access-log indicators for limit and index problems
Before you start:
- Install 389 Directory Server — running instance with a suffix (this lab uses
ldap1ondc=example,dc=com) - dsconf commands — online configuration
- Configure 389 Directory Server Indexes for Faster LDAP Searches —
notes=Uand missing-index diagnosis
Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.
The lab instance is ldap1 on ldap1.example.com with LDAP port 389. The suffix dc=example,dc=com is served by backend userroot.
Understand search resource limits
Directory Server applies limits at several layers. Instance-wide settings in cn=config cap ordinary searches for most bind identities. Look-through, ID-list, paged look-through, paged ID-list, and range look-through limits live on the global LDBM database plug-in entry at cn=config,cn=ldbm database,cn=plugins,cn=config. The command dsconf ldap1 backend config get reads that global database configuration; it does not read an individual backend such as userroot. Per-entry operational attributes on a bind DN can tighten or relax limits for one application account.
LDAP client bind
|
v
Per-entry operational limits (nsSizeLimit, nsTimeLimit, ...)
|
v
Global instance limits (nsslapd-sizelimit, nsslapd-timelimit, ...)
|
v
Global LDBM plug-in limits (nsslapd-lookthroughlimit, nsslapd-idlistscanlimit, ...)
|
v
Search executes or stops with LDAP result 4 (size limit) or 3 (time limit)| Limit | Global attribute | User-level attribute | What it controls |
|---|---|---|---|
| Size | nsslapd-sizelimit |
nsSizeLimit |
Maximum entries returned to the client |
| Time | nsslapd-timelimit |
nsTimeLimit |
Maximum seconds spent processing one search |
| Look-through | nsslapd-lookthroughlimit |
nsLookThroughLimit |
Maximum candidate entries examined |
| ID-list scan | nsslapd-idlistscanlimit |
nsIDListScanLimit |
Maximum entry IDs loaded from one index key before the search is treated as unindexed |
| Fine-grained ID-list | nsIndexIDListScanLimit |
— | Override ID-list behaviour for a specific index entry in a specific backend |
| Paged size | nsslapd-pagedsizelimit |
nsPagedSizeLimit |
Maximum entries returned by a search using the simple paged-results control |
| Paged look-through | nsslapd-pagedlookthroughlimit |
nsPagedLookThroughLimit |
Look-through cap for paged searches |
| Paged ID-list scan | nsslapd-pagedidlistscanlimit |
nsPagedIDListScanLimit |
ID-list cap for paged searches |
| Range look-through | nsslapd-rangelookthroughlimit |
Not available | Look-through cap for range searches |
Size limit:
How many entries can be returned
Look-through limit:
How many entries may be examined to find those results
ID-list scan limit:
How many candidate IDs may be loaded from an indexA search can return only one entry but still examine thousands of candidates.
Clarifications that prevent the most common mistakes:
- Directory Manager bypasses global size and time limits. Testing
nsslapd-sizelimitwith Directory Manager will not show the same behaviour application accounts see. - Per-user limits override global defaults for that bind DN. When
uid=reporting-appcarriesnsSizeLimit: 2, that value wins overnsslapd-sizelimitfor searches bound as that user. -1means unlimited only where the attribute schema documents that value. Use it sparingly on trusted accounts.- Paged limit
0inherits the ordinary limit. Whennsslapd-pagedsizelimitis0, paged searches usensslapd-sizelimit. The same fallback design applies tonsslapd-pagedlookthroughlimitandnsslapd-pagedidlistscanlimit. Use-1only when the paged limit must be explicitly unlimited. - Client page size is separate from
nsslapd-pagedsizelimit. The client requests a batch size through the paged-results control, for exampleldapsearch -E pr=50/noprompt.nsslapd-pagedsizelimitcaps the total entries returned by the complete paged search operation. notes=Uis not only a missing-index signal. It also appears when an index key matches more entry IDs thannsslapd-idlistscanlimitallows. See Configure LDAP indexes for index creation.
Check current search limits
Read the active instance configuration before changing anything. Recording the baseline makes rollback straightforward.
dsconf ldap1 config get nsslapd-sizelimit nsslapd-timelimit nsslapd-pagedsizelimitnsslapd-sizelimit: 2000
nsslapd-timelimit: 3600
nsslapd-pagedsizelimit: 0The lab allows up to 2000 entries per ordinary search and 3600 seconds of processing time. nsslapd-pagedsizelimit: 0 means paged searches inherit nsslapd-sizelimit.
Read the global LDBM database plug-in limits:
dsconf ldap1 backend config get | grep -E 'lookthrough|idlist|paged|rangelookthrough'nsslapd-lookthroughlimit: 5000
nsslapd-pagedlookthroughlimit: 0
nsslapd-idlistscanlimit: 4000
nsslapd-pagedidlistscanlimit: 0
nsslapd-rangelookthroughlimit: 5000On the tested upstream 389 Directory Server 3.2.0 build, dsconf reported nsslapd-idlistscanlimit: 4000. Do not assume that value on other builds. Current RHDS 13 documentation marks the global setting as deprecated and documents different defaults. Inspect the active value on the installed release.
Paged look-through and paged ID-list values of 0 inherit nsslapd-lookthroughlimit and nsslapd-idlistscanlimit respectively.
Create the reporting-app service account when it does not exist yet. Save reporting-app.ldif:
dn: uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: Reporting Application
sn: Application
uid: reporting-app
userPassword: ReportingAppPass!ldapadd -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f reporting-app.ldifGrant read access under ou=People before limit tests. Save reporting-app-aci.ldif:
dn: ou=people,dc=example,dc=com
changetype: modify
add: aci
aci: (targetattr="*")(version 3.0; acl "reporting-app read people"; allow (read,search,compare) userdn="ldap:///uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com";)ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f reporting-app-aci.ldifVerify the ACI was accepted, then confirm reporting-app can search under ou=people. See ACI examples when the bind succeeds but searches return no entries.
Configure search size, time, and look-through limits
Size limit
Lower the global size limit temporarily so the lab can demonstrate result code 4:
dsconf ldap1 config replace nsslapd-sizelimit=3Successfully replaced value(s) for 'nsslapd-sizelimit': '3'No restart is required for nsslapd-sizelimit.
Test with Directory Manager first to confirm the bypass:
Directory queries in this section use the ldapsearch command.
ldapsearch -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -b "ou=people,dc=example,dc=com" -s sub "(objectClass=inetOrgPerson)" dn 2>&1 | tail -3Directory Manager still returns every matching entry even when nsslapd-sizelimit=3. Use an application bind DN when you validate limit changes.
Bind as reporting-app:
ldapsearch -x -H ldap://ldap1.example.com:389 -D "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com" -W -b "ou=people,dc=example,dc=com" -s sub "(objectClass=inetOrgPerson)" dnresult: 4 Size limit exceeded
# numEntries: 3The server returned three entries and stopped with LDAP result code 4.
Restore the global size limit:
dsconf ldap1 config replace nsslapd-sizelimit=2000Time limit
Set a global time limit in seconds:
dsconf ldap1 config replace nsslapd-timelimit=60Successfully replaced value(s) for 'nsslapd-timelimit': '60'A tiny lab suffix often finishes every search before the limit is reached, so this build may not produce err=3 during testing. On a sufficiently large suffix, bind as a non-Directory-Manager account, run an intentionally expensive search, and look for Time limit exceeded (3) in the client output and access log.
Restore the lab default when testing finishes:
dsconf ldap1 config replace nsslapd-timelimit=3600Look-through limit
Raise the global look-through limit only when representative filters genuinely need to examine more candidates:
dsconf ldap1 backend config set --lookthroughlimit=10000Successfully updated database configurationdsconf ldap1 backend config get | grep nsslapd-lookthroughlimitnsslapd-lookthroughlimit: 10000Look-through limits apply while the server evaluates a filter, not only when entries are returned. A filter that returns 250 entries can still examine 8,000 candidates along the way.
Restore the original value after the demonstration:
dsconf ldap1 backend config set --lookthroughlimit=5000Do not increase the look-through limit merely to hide an indexing problem.
Configure paged and range search limits
Simple paged results let a client walk a large result set in smaller chunks using the LDAP paged-results control.
| Setting | What it controls |
|---|---|
nsslapd-pagedsizelimit / nsPagedSizeLimit |
Maximum entries returned by a complete paged search operation |
-E pr=50/noprompt on ldapsearch |
Client-requested page batch size for one response |
Check the current paged size limit:
dsconf ldap1 config get nsslapd-pagedsizelimitnsslapd-pagedsizelimit: 0When the value is 0, paged searches inherit nsslapd-sizelimit. Set a positive value such as 500 with dsconf ldap1 config replace nsslapd-pagedsizelimit=500 when a complete paged search must not return more than 500 entries total. The client's requested page size in the paged-results control remains a separate value.
Paged look-through and paged ID-list limits are global LDBM plug-in settings:
dsconf ldap1 backend config get | grep -E 'pagedlookthrough|pagedidlist'nsslapd-pagedlookthroughlimit: 0
nsslapd-pagedidlistscanlimit: 0Values of 0 inherit nsslapd-lookthroughlimit and nsslapd-idlistscanlimit. Use -1 on the paged attribute when the paged search must be explicitly unlimited.
Range searches use nsslapd-rangelookthroughlimit. The lab default is 5000. Directory Manager is not exempt from range look-through limits.
Test the simple paged-results control
This command proves the client and server support paging. It does not by itself prove enforcement of nsslapd-pagedsizelimit; that requires a suffix large enough to exceed the configured total paged cap.
ldapsearch -x -H ldap://ldap1.example.com:389 -D "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com" -W -b "ou=people,dc=example,dc=com" -s sub "(objectClass=inetOrgPerson)" uid -E pr=50/noprompt 2>&1 | tail -6When paging works, the access log records notes=P on the RESULT lines. Test total paged-search enforcement separately on a populated suffix with nsslapd-pagedsizelimit or nsPagedSizeLimit set below the result count.
Configure limits for one user or application
Service accounts often need tighter caps than the global defaults. Store overrides on the user entry as operational attributes. The example below demonstrates common controls; it is not the complete supported set. Official documentation also lists nsIDListScanLimit, nsPagedLookThroughLimit, and nsPagedIDListScanLimit. Range look-through has no per-user counterpart.
Save reporting-app-limits.ldif:
dn: uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com
changetype: modify
replace: nsSizeLimit
nsSizeLimit: 2
-
replace: nsTimeLimit
nsTimeLimit: 60
-
replace: nsLookThroughLimit
nsLookThroughLimit: 5000
-
replace: nsPagedSizeLimit
nsPagedSizeLimit: 100ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f reporting-app-limits.ldifRead the effective per-user limits with +:
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=*)" "+" nsSizeLimit nsTimeLimit nsLookThroughLimit nsPagedSizeLimitnsSizeLimit: 2
nsTimeLimit: 60
nsLookThroughLimit: 5000
nsPagedSizeLimit: 100With nsslapd-sizelimit at 2000, the per-user nsSizeLimit: 2 still wins for this bind DN:
ldapsearch -x -H ldap://ldap1.example.com:389 -D "uid=reporting-app,ou=ServiceAccounts,dc=example,dc=com" -W -b "ou=people,dc=example,dc=com" -s sub "(objectClass=inetOrgPerson)" dnresult: 4 Size limit exceeded
# numEntries: 2Protect operational limit attributes with ACIs so users cannot raise their own caps.
Tune ID-list scan limits
When one index key points at a very large candidate set, Directory Server can treat the search as partially unindexed even though the attribute is indexed.
Indexed value matches 50,000 entry IDs
|
v
ID-list scan limit is 4,000
|
v
Server stops loading that index list
|
v
Search is processed as an unindexed searchCheck the active global value:
dsconf ldap1 backend config get | grep nsslapd-idlistscanlimitnsslapd-idlistscanlimit: 4000On the tested upstream 389 Directory Server 3.2.0 build, dsconf reported 4000. Current RHDS 13 documentation states that changes to the global ID-list setting affect subsequent searches without a restart. Because the attribute is deprecated and its defaults vary by release, inspect rather than change it unless performance testing demonstrates a specific need. Prefer selective nsIndexIDListScanLimit rules, narrower filters, and better indexes over broadly raising the global setting.
Fine-grained ID-list rules
Fine-grained rules modify a specific index entry in a specific backend. The objectClass equality index under userroot is a common target for (&(objectClass=inetOrgPerson)(...)) filters.
limit=0 rule merely because objectClass matches many entries. Confirm through access logs and representative filters that another selective indexed term can efficiently drive the search.
Save objectclass-idlist-limit.ldif:
dn: cn=objectclass,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
changetype: modify
add: nsIndexIDListScanLimit
nsIndexIDListScanLimit: limit=0 type=eq flags=AND values=inetOrgPersonldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f objectclass-idlist-limit.ldifThe syntax is limit=NNN [type=eq[,sub,...]] [flags=AND[,XXX,...]] [values=val[,val,...]]. Setting limit=0 for objectClass=inetOrgPerson in an AND filter deliberately avoids building an ID list for that value.
| Value | Meaning |
|---|---|
-1 |
Unlimited ID list (where supported on the fine-grained rule) |
0 |
Do not use the ID list for the matching condition |
| Positive number | Maximum IDs loaded |
Remove the rule when the lab demonstration finishes. Save remove-objectclass-idlist-limit.ldif:
dn: cn=objectclass,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
changetype: modify
delete: nsIndexIDListScanLimit
nsIndexIDListScanLimit: limit=0 type=eq flags=AND values=inetOrgPersonldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -W -f remove-objectclass-idlist-limit.ldifDiagnose search-limit problems in access logs
/var/log/dirsrv/slapd-ldap1/accessgrep -E 'notes=.*(A|U|P)|err=4|err=3' /var/log/dirsrv/slapd-ldap1/access | tail -5[17/Jul/2026:23:47:01 +0530] conn=79 op=1 RESULT err=0 tag=101 nentries=1 etime=0.014392270 notes=U details="Partially Unindexed Filter"
[17/Jul/2026:23:47:19 +0530] conn=85 op=1 RESULT err=4 tag=101 nentries=3 etime=0.004090297
[17/Jul/2026:23:47:47 +0530] conn=3 op=7 RESULT err=0 tag=101 nentries=50 etime=0.022746790 notes=P details="Paged Search"| Field | Meaning |
|---|---|
notes=A |
Every candidate filter attribute was unindexed; a full scan was required |
notes=U |
At least one term was unindexed, or an index key exceeded nsslapd-idlistscanlimit |
notes=P |
Simple paged-results control was used |
err=4 |
Size limit exceeded |
err=3 |
Time limit exceeded |
High etime |
The operation took longer to complete on the server |
notes=U does not always mean a missing index file. When every indexed attribute is present but notes=U persists, check whether the ID-list scan limit was exceeded before adding more indexes.
Correlate SRCH, BIND, and RESULT lines by conn and op numbers.
Test and troubleshoot
| Test | Identity | Setting | Expected signal |
|---|---|---|---|
| Global size cap | reporting-app |
nsslapd-sizelimit=3 |
err=4 with nentries equal to the cap |
| Per-user size cap | reporting-app |
nsSizeLimit: 2 |
err=4 after two entries |
| Directory Manager bypass | Directory Manager | nsslapd-sizelimit=3 |
More than three entries returned |
| Paged control | reporting-app |
-E pr=50/noprompt |
notes=P in access log |
| ID-list threshold | Application bind | nsslapd-idlistscanlimit |
notes=U on broad indexed filters |
| Symptom | Likely cause | Fix |
|---|---|---|
| Size limit never triggers | Tests use Directory Manager | Repeat with the application bind DN |
| Application hits size limit unexpectedly | Per-user nsSizeLimit is lower than global |
Read operational attributes with ldapsearch ... "+" |
| Paged search stops below client page size | Total paged cap hit | Check nsslapd-pagedsizelimit or nsPagedSizeLimit; remember 0 inherits the ordinary limit |
| Time limit never triggers in a small lab | Suffix too small | Test on a populated suffix with a non-Directory-Manager bind |
Security and operational recommendations:
- Test limit changes with the real application bind DN, not Directory Manager.
- Avoid
-1unlimited size or time limits except on tightly controlled administrative accounts. - Keep per-service-account limit attributes in change control alongside ACIs.
- Use simple paged results for large directory browsers instead of raising global size limits alone.
- Treat
notes=Uas a limit or index design problem before blindly raisingnsslapd-idlistscanlimit. - Change one setting at a time and retest with access logs.
What's next
After you complete this guide, continue with:
- Configure LDAP Threads and Connections in 389 Directory Server — worker threads under heavy search load
- Configure Virtual List View Indexes in 389 Directory Server — paged browsing for large result sets
- Tune LMDB, Entry Cache and DN Cache in 389 Directory Server — LMDB tuning when limits are raised
- Benchmark 389 Directory Server Performance with ldclt and logconv — measure the effect of limit changes
Summary
- Instance attributes in
cn=configcap ordinary searches; global LDBM plug-in attributes control look-through and ID-list behaviour. - Directory Manager bypasses global size and time limits; validate changes with application bind accounts.
- Per-entry operational attributes override global defaults for that bind DN.
- Paged limit
0inherits the corresponding ordinary limit;-1means explicitly unlimited where the schema allows it. nsslapd-idlistscanlimitbehaviour varies by release; prefer fine-grainednsIndexIDListScanLimitrules and better filters over broad global changes.notes=Usignals unindexed work or an ID-list cap, not only a missing index file.
For worker threads, listeners, and connection descriptors, see Configure LDAP threads and connections.
References
- Red Hat Directory Server 13 — Searching entries and tuning searches (§10.5 resource limits)
- Red Hat Directory Server 13 — Configuration and schema reference (
nsslapd-idlistscanlimitand related attributes) - Red Hat Directory Server 13 — Log files reference (access-log search indicators)

