Skip to content

Embedded mode

shard-db can run in-process inside your application — no daemon, no TCP socket, no separate process. You open a data directory, run queries synchronously, and close when you're done. All the same storage, indexes, and query capabilities are available; the only things missing are the TCP server and its config knobs (PORT, TLS_*, THREADS, etc.).

When to use it

Use daemon mode Use embedded mode
Multiple applications share one database Single application owns the data
Remote access required All access is in-process
Multi-language clients (Python, Go, …) C, C++, or Node.js / Bun
Hot reload / live config changes Restart is acceptable

C API

Include shard_db.h (exported alongside libshard-db.a during ./build.sh):

#include "shard_db.h"

Open

ShardDb *db = shard_db_open("/path/to/data");
if (!db) { /* check stderr */ }

db_root must be an existing, writable directory. One instance per process (single-instance guard enforced with an atomic flag).

Query

char  *out     = NULL;
size_t out_len = 0;

int rc = shard_db_query(db,
    "{\"mode\":\"count\",\"dir\":\"default\",\"object\":\"users\"}",
    &out, &out_len);

if (rc == 0) {
    printf("%.*s\n", (int)out_len, out);   /* e.g. 42 */
    shard_db_free_result(out);
}

shard_db_query is thread-safe — multiple threads may call it concurrently on the same handle. Returns 0 on success, -1 on allocation failure. The response is the same JSON string the daemon would return over TCP; parse it with any JSON library.

Always free the result with shard_db_free_result(out).

Close

shard_db_close(db);

Shuts down the CPU and I/O thread pools, flushes caches, and frees all resources. After this call the pointer is invalid.

Log handler

By default embedded mode is silent — no log files, no ring buffer. Register a callback to receive events:

void my_log(int type, const char *msg, void *userdata) {
    /* msg: "YYYY-MM-DD HH:MM:SS LEVEL [subsystem] text\n" */
    if (type <= SHARD_DB_LOG_WARN)
        fprintf(stderr, "[shard-db] %s", msg);
}

shard_db_set_log_handler(db, my_log, NULL);

Log type constants:

Constant Value When
SHARD_DB_LOG_ERROR 1 Internal errors
SHARD_DB_LOG_WARN 2 Warnings
SHARD_DB_LOG_INFO 3 General info
SHARD_DB_LOG_DEBUG 4 Verbose debug
SHARD_DB_LOG_AUDIT 5 Auth / write audit trail
SHARD_DB_LOG_SLOW 6 Slow-query threshold crossed

Thread safety: the handler is called from whichever thread emits the event — including shard-db's internal worker threads. The handler must be thread-safe.

Timing: set the handler after shard_db_open returns. Log events that occur during open itself (schema load, recovery) are emitted before the handler is registered and will not be delivered.

Configuration

shard-db reads db.env from the process's current working directory on shard_db_open, if the file exists. DB_ROOT inside the file is ignored — the db_root argument to shard_db_open is always authoritative.

Useful knobs for embedded mode:

# db.env  (place in your app's working directory)
SLOW_QUERY_MS=200       # default 500 — log queries slower than this
GLOBAL_LIMIT=10000      # default 100000 — max records returned per query
FCACHE_MAX=4096         # default 4096 — open file-handle cache size
TOKEN_CAP=1024          # default 1024 — token table buckets
LOG_LEVEL=3             # default 3 — 1=ERROR 2=WARN 3=INFO 4=DEBUG

If no db.env is present all settings stay at their compiled defaults. The file is only read once at open time; changing it after shard_db_open has no effect until the next open.

Linking

./build.sh produces build/bin/libshard-db.a and build/bin/shard_db.h.

CFLAGS  += -I/path/to/build/bin
LDFLAGS += -L/path/to/build/bin -lshard-db -lpthread
# On Linux also: -lm
# With TLS enabled: -lssl -lcrypto

Limitations

  • One instance per process. A second shard_db_open call returns NULL until the first is closed.
  • No TCP server. Daemon config knobs that relate to the TCP layer (PORT, TLS_*, THREADS, WORKERS, MAX_REQUEST_SIZE) are parsed from db.env if present but have no effect. MAX_CONCURRENT_QUERIES does not cap concurrency in embedded mode but does influence the per-query memory budget auto-tune.
  • Startup logs not delivered. Events emitted during shard_db_open occur before the handler is registered. If you need to capture them, start the daemon, redirect its log to your log pipeline, and use the TCP API instead.