Overview
Maintaining the performance and health of your ELIPS database is critical for long-running deployments. This page documents the APIs available for managing collection and client maintenance in Python, including managing HNSW tombstones, reclaiming disk space, and monitoring the lifecycle of your database.
HNSW Compaction & Tombstones
When you delete a record in ELIPS using collection.delete(), the node is not immediately removed from the HNSW graph to avoid heavy lock contention. Instead, it is marked as a tombstone.
The search algorithm uses an adaptive ef beam: when tombstones build up, query() dynamically scales the search width by the ratio of total nodes to live nodes. This ensures that the search beam still yields enough live hits, allowing recall to stay within 0.15 of baseline even at a 50% delete ratio, while the graph size remains bounded.
You can check how many tombstones are pending removal using the collection.pending_removals property.
Vacuum
To reclaim the space held by tombstones in the index, use vacuum(). It performs a self-compaction of the graph index without rewriting the on-disk snapshot, making it cheap and safe to use even on in-memory databases.
collection.vacuum()— Vacuums a specific collection. It's a cheap no-op if nothing is tombstoned.client.vacuum()— Reclaims tombstoned index space across every collection in the database.
import elips
client = elips.PersistentClient("/data/vec", dimension=128)
docs = client.get_or_create_collection("docs")
# Ingest then delete a batch
ids = [docs.add(embedding=[0.0] * 128, metadata={"i": i}) for i in range(1000)]
docs.delete(ids[:200])
# Check tombstone pressure
print(docs.pending_removals) # 200
# Vacuum: cheap, works on in-memory DBs too
docs.vacuum()
print(docs.pending_removals) # 0
# Client-level vacuum across all collections
client.vacuum()Rebuild
Unlike vacuum(), collection.rebuild() completely reconstructs the backing index from stored records. It is more expensive but creates a perfectly fresh HNSW graph without the fragmentation that might accumulate after millions of updates.
For quantized collections, collection.compress() (alias train) trains the codebook from the stored vectors so compressed search can be served.
HNSW Params
The compaction_ratio parameter controls the tombstone fraction that triggers auto-compaction. By default, it is set to 0.2 (20%). Setting it to 0.0 disables auto-compaction.
# HnswParams with compaction_ratio
params = elips.HnswParams(
max_connections=16,
ef_construction=200,
ef_search=50,
compaction_ratio=0.15, # compact when 15% tombstoned
)
client = elips.PersistentClient("/data/vec", dimension=128, index="graph", hnsw=params)Read-Only Mode & Sealing
You can explicitly control the mutability of your collections:
collection.read_only: ReturnsTruewhen the collection is in read-only mode and refuses mutations.collection.freeze(frozen=True): Freezes the collection so further mutations are rejected. Passfrozen=Falseto unfreeze.collection.sealed: ReturnsTrueonce the owning client is closed. Writes to a sealed collection immediately raise an error rather than silently failing to persist data to memory that will never be checkpointed.
Inspecting Records
To look at stored records without running a similarity search, use collection.peek(n) (a quick sample) or collection.get(...) (by ids or a where filter). Both return Row objects.
sample = docs.peek(10) # list[Row]
print(len(sample)) # up to 10
print(docs.count()) # total live records
# Scan a filtered page without loading everything
rows = docs.get(where=elips.Filter().field("kind").equals("design"), limit=100)Note: For large collections, prefer get() with a filter and limit instead of fetching every record, to avoid copying the entire dataset into memory at once.
Client Lifecycle
The Client / PersistentClient object exposes several maintenance and lifecycle methods:
client.compact()— Rebuilds every collection index from scratch and checkpoints the state. Ideal for periodic cleanup on on-disk databases (unlikevacuum, it does not work on in-memory DBs).client.checkpoint()— Flushes current state and WAL to disk for durability.client.close()— Triggers a final checkpoint, releases locks, and seals every collection.
Use the client as a context manager so it is always closed cleanly:
with elips.PersistentClient("/data/vec", dimension=128) as client:
docs = client.get_or_create_collection("docs")
# ... work ...
client.checkpoint()
# close() runs automatically on exitThe low-level native handle is available via client.native, and the resolved settings via client.config.
Client Maintenance
The client exposes database-wide maintenance helpers:
client.vacuum()— Vacuums all collections.client.collection_names() -> list[str]— Lists all collection names (aliaslist_collections()).client.pending_writes() -> list[WalRecord]— Returns all pending WAL entries.
Collection Health
For detailed diagnostics, collection.health() returns a CollectionHealth dataclass which includes metrics like the tombstone_ratio property. This is useful for building operational dashboards and determining when to trigger a manual vacuum.
Operational Patterns
For production applications, follow this checklist to ensure consistent performance:
- Monitor tombstones: Periodically check
collection.pending_removalsorcollection.health().tombstone_ratio. - Vacuum proactively: Call
vacuum()when thetombstone_ratioexceeds your configuredcompaction_ratiothreshold, or rely on auto-compaction. - Use checkpoints: Periodically call
checkpoint()in long-running serving loops to ensure regular durability without pausing queries. - Scheduled compactions: Call
compact()before planned long downtime windows to flush the WAL and completely rebuild indices on disk.
Common Pitfalls
- Never call
collection.rebuild()on a hot collection under active concurrent search load unless you have a second replica serving the traffic. - Don't expect
compact()to work on an in-memory database; usevacuum()instead. - Writing to a collection after calling
client.close()will raise an error because the collection is sealed. Be sure to stop ingest traffic before closing the client.
See also: Python SDK, Algorithms, Storage.