Skip to content

SearchIndex.drop_keys should use UNLINK instead of DEL #600

@vishal-bala

Description

@vishal-bala

Current behavior

SearchIndex.drop_keys (redisvl/index/index.py:826) issues a synchronous DEL:

def drop_keys(self, keys: str | list[str]) -> int:
    if isinstance(keys, list):
        return self._redis_client.delete(*keys)
    else:
        return self._redis_client.delete(keys)

DEL reclaims memory on the main thread. A single drop of tens of thousands of keys stalls the server proportionally to the freed keyspace. For a SemanticCache use case where scope-targeted invalidation routinely produces sweeps in the 10K–1M+ range (e.g., a policy version rollover in a multi-tenant deployment), this is a customer-visible latency event on every invalidation.

Proposed change

Switch the bulk path to UNLINK, which queues memory reclamation on a background thread:

return self._redis_client.unlink(*keys)

UNLINK returns the same count semantics. It is available on Redis 4+ so there is no minimum-version concern for current RedisVL targets.

If there is a reason to preserve DEL semantics for some callers, expose use_unlink: bool = True and default to True.

Backwards compatibility

UNLINK is a strict superset of DEL for this use case. The only observable difference is that the keys may not be immediately reclaimed from a MEMORY USAGE standpoint — which is the point. Behavior in tests and at the protocol level is identical.

Notes

Surfaced while writing a scoped semantic caching architecture spec. Also relevant to SemanticCache.drop(), which calls drop_keys under the hood when invoked with keys=.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomersindexSearchIndex or AsyncSearchIndex class related

    Type

    No type

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions