Pulse 2025 Product Roundup: From Monitoring to AI-Native Control Plane

Read more

Elasticsearch Document Level Security (DLS) - Common Issues and Troubleshooting

Document Level Security (DLS) in Elasticsearch restricts which documents a user can read based on a query defined within a role. Elasticsearch appends the DLS query as a filter to every search request, transparently excluding documents that do not match. DLS applies only to read operations - it does not affect indexing or updates.

Role Definition with DLS Queries

DLS is configured in the indices privileges of a role definition. The query field accepts any valid Elasticsearch Query DSL:

PUT /_security/role/restricted_viewer
{
  "indices": [
    {
      "names": ["logs-*"],
      "privileges": ["read"],
      "query": {
        "term": { "department": "engineering" }
      }
    }
  ]
}

This role restricts users to documents where department equals engineering. The query runs in filter context, so no scoring occurs. Template role queries inject user attributes at runtime using and placeholders:

PUT /_security/role/user_scoped
{
  "indices": [
    {
      "names": ["records-*"],
      "privileges": ["read"],
      "query": {
        "template": {
          "source": {
            "term": { "owner": "" }
          }
        }
      }
    }
  ]
}

To use , the user must have a department key set in their metadata via the user API. If the metadata key is missing, the template renders an empty string, and the query silently matches no documents.

Common Issues with DLS Queries

Silent total filtering is the most disorienting DLS problem. If the role query contains a syntax error or references a nonexistent field, Elasticsearch does not throw an error. The query matches zero documents, and the user sees empty results with no indication that DLS is the cause. Always test DLS queries as standalone searches before embedding them in role definitions.

Multiple roles with conflicting DLS follow specific merge logic. Two roles with different DLS queries on the same index are combined with logical OR - the user sees documents matching either query. But if one role has a DLS query and another grants unrestricted access (no query field), the unrestricted role wins and the user sees all documents.

Interaction with aliases is a known weak point. Filtered aliases are not a substitute for DLS. Elasticsearch does not consistently apply alias filters across all API paths, creating security gaps.

Data streams work with DLS, but the DLS query's target fields must exist consistently across all backing indices. A mapping change in newer backing indices that removes or renames a field used in the DLS query causes silent filtering on those indices.

Performance Impact

For simple term queries, the DLS overhead is negligible. Complex DLS queries - nested boolean logic, scripts, or queries on non-indexed fields - add measurable latency to every search. The DLS filter is combined with the user's query at execution time, so query cache hit rates decrease in clusters where many users have distinct DLS queries. Each unique combination of user search plus DLS filter generates a separate cache entry.

Prefer term and terms queries over match or bool with many clauses. Avoid scripted queries in DLS role definitions. Monitor search latency closely after enabling DLS on clusters with heavy search traffic.

Limitations

Several Elasticsearch features behave differently under DLS:

  • Aggregations: DLS filters apply to aggregation results, but users can still infer field names and term distributions from visible documents. Combine DLS with Field Level Security (FLS) if field-level confidentiality matters.
  • Suggesters: Ignored when DLS is active.
  • Search profiling: The Profile API cannot be used when DLS is enabled.
  • Terms enum API: Returns no terms when DLS is enabled.
  • Update operations: The update API and bulk updates are not supported on DLS-enabled indices. Do not grant write privileges on roles with DLS restrictions.
  • has_child and has_parent queries: Not supported inside DLS role query definitions.
  • DLS combined with FLS: All fields referenced in the DLS query must remain visible under FLS. If FLS hides a field the DLS query filters on, the result is unpredictable - typically all documents are excluded. Cross-check FLS field lists against DLS query fields.

Debugging and Verification

The _has_privileges API verifies whether a user has specific privileges on an index, but it does not reveal DLS query details. To test what a DLS-restricted user actually sees, use the _search API while authenticating as that user with the run_as feature or by logging in directly.

Audit logging captures access events and can show when DLS restricts a user's view. Enable the audit log in elasticsearch.yml:

xpack.security.audit.enabled: true

Filter audit logs for access_granted and access_denied events to trace DLS enforcement. For deeper inspection, compare search output as a superuser versus a DLS-restricted user on the same index and query. Discrepancies in hit counts directly indicate DLS filtering. When template queries are involved, verify user metadata with GET /_security/user/<username> to confirm the template renders the expected query.

Pulse - Elasticsearch Operations Done Right

Pulse can solve your Elasticsearch issues

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.