Best Practices

Lessons learned from integrating ChronDB in real-world applications. These apply to all language bindings (Rust, Python, Node.js, etc.) since they stem from the ChronDB core (GraalVM native image + Git storage).

Values must be JSON objects

put() requires a JSON object as the document value. Scalar values (numbers, strings, booleans) will fail silently or return an error.

// ❌ Fails
put("meta:counter", 42)

// ✅ Works
put("meta:counter", {"value": 42})

This applies to all bindings — always wrap scalars in an object.

Batch writes: open once, write many, close

Opening ChronDB has overhead (GraalVM isolate startup). For bulk operations, open once and write all documents in a single session.

// ✅ Fast — single open/close
db = open_path("./mydb")
for doc in documents:
    db.put(doc.id, doc.data)
// close/drop db

// ❌ Slow — reopening per document
for doc in documents:
    db = open_path("./mydb")
    db.put(doc.id, doc.data)
    // close/drop db

The difference is orders of magnitude for large batches. Each open_path() creates or attaches to a GraalVM isolate with a dedicated worker thread.

GraalVM heap exhaustion on large datasets

For sessions with thousands of put() calls, the GraalVM native image may run out of heap space:

Workaround: Split large write batches into smaller sessions. Open, write a batch (e.g., 1000 docs), close, then reopen for the next batch. This allows GraalVM to reclaim memory between sessions.

Index corruption after interrupted writes

If the process is killed during a write operation (Ctrl+C, SIGKILL, OOM), the Lucene index may be left with a stale write.lock file. The next open_path() will fail:

Recovery: Delete the index directory and reopen. ChronDB rebuilds the index automatically from the Git data — no data is lost.

For production applications, implement automatic recovery: if open_path() fails, delete the index directory and retry.

Git data directory is a bare repository

ChronDB stores data as a bare Git repository. The data directory contains Git objects directly (HEAD, objects/, refs/) without a .git/ subdirectory.

If you need to interact with the Git repo directly, use --git-dir:

Remote sync

Since v0.2.1, ChronDB supports native remote Git operations via setup_remote(), push(), pull(), and fetch(). Use these instead of running Git CLI commands manually.

Note: Passing a Git URL directly to open_path() does not clone the repository — it creates a literal directory with that name. Always use a local path and configure the remote separately with setup_remote().

list_by_prefix response format

list_by_prefix() returns a JSON array of objects. Each object includes an id field with the document key:

Use the id field to extract document keys when iterating results.

Idle timeout for long-running services

ChronDB's GraalVM isolate consumes CPU and memory even when idle. For services with sporadic database access (daemons, MCP servers, background workers), use idle_timeout to automatically suspend the isolate.

The isolate suspends after the timeout and transparently reopens on the next operation.

Don't use for: Short-lived CLI tools (just open and close normally) or high-throughput services where the isolate never goes idle.

Last updated

Was this helpful?