Guides

Embedded Go

Open a database in your application and work with records using the native Go API.

Open and close

zeedb.Open opens an existing database or initializes a new directory. It acquires an exclusive process lock and verifies persisted checksums before returning.

db, err := zeedb.Open("./data", zeedb.Options{
    Durability: zeedb.Durable,
})
if err != nil {
    return err
}

Always call Close and handle its error. It syncs pending WAL writes, closes files, and releases the process lock. It does not force an SSTable checkpoint.

In a function with a named err return, preserve a close error:

defer func() { err = errors.Join(err, db.Close()) }()

Import errors from the standard library for this pattern. Close is idempotent.

Put and get

ctx := context.Background()
err = db.Put(ctx, "users", []byte("1024"), []byte(`{"name":"Ada"}`))
if err != nil {
    return err
}

value, err := db.Get(ctx, "users", []byte("1024"))
if err != nil {
    return err
}
fmt.Println(string(value))

Values are opaque bytes. JSON is an application encoding; ZeeDB does not validate or index JSON fields. Put replaces the existing record. Empty values are valid; empty keys are not.

Inputs are copied on writes. Returned keys and values belong to the caller and can be changed without changing the database.

Read a version

record, err := db.GetRecord(ctx, "users", []byte("1024"))
if err != nil {
    return err
}
fmt.Printf("version=%d value=%s\n", record.Version, record.Value)

Version is the sequence of the commit that last wrote this record. It is not a compare-and-swap token enforced by the current API. There is no optimistic concurrency write method yet.

Delete a record

if err := db.Delete(ctx, "users", []byte("1024")); err != nil {
    return err
}

A delete hides an existing record and is safe to repeat. Reads of missing or deleted keys return ErrNotFound; use errors.Is to inspect errors.

Concurrency and cancellation

One handle supports concurrent callers. Commits use an exclusive lock; reads and scans hold a shared lock and observe one committed state. A sequence of separate API calls is not a read/write transaction.

Contexts are checked at operation boundaries, after lock acquisition, and during scans. Waiting for a mutex or OS I/O is not interruptible. After a WAL append or checkpoint begins, cancellation cannot undo the persistent operation.

An I/O failure during a write or checkpoint makes the commit result indeterminate and poisons the handle. Close and reopen it, then reconcile application state before retrying a non-idempotent operation.

See atomic batches, range scans, and errors.

Something to improve?Edit this page on GitHub