phoenixdb library

PhoenixDB — an ACID-compliant embedded key/value database for Dart.

The storage engine is written in Rust (B+Tree index, MVCC transactions, write-ahead log, CRC32-checksummed 4 KiB pages) and reached through a zero-overhead dart:ffi binding.

Synchronous use

final db = PhoenixDatabase.open('data.pdb');
db.insert(utf8Key('hello'), utf8Value('world'));
print(db.get(utf8Key('hello')));
db.close();

AsyncPhoenixDB runs every operation on a worker isolate so disk I/O never blocks the UI thread:

final db = await AsyncPhoenixDB.open('data.pdb');
await db.transaction((txn) async {
  await db.insert(utf8Key('a'), utf8Value('1'), txnId: txn);
  await db.insert(utf8Key('b'), utf8Value('2'), txnId: txn);
});
await db.close();

PhoenixDB also ships an embedded k-NN index (HNSW over memory-mapped f32 vectors) for local-first semantic search:

final index = await AsyncPhoenixVectorDB.open('vectors.pvec', dimensions: 384);
await index.insert('doc-1', embedding);
final hits = await index.search(VectorQuery(query, k: 5));
print(hits.first.id);
await index.close();

A PhoenixCollection keeps text, JSON metadata and embeddings together and searches them in one call — vector similarity, BM25 keywords, metadata filters, rank fusion and MMR diversification:

final kb = await AsyncPhoenixCollection.open('kb', dimensions: 384);
await kb.upsert([
  Document('doc-1', text: 'PhoenixDB runs on-device',
      metadata: {'lang': 'en'}, vector: embedding),
]);
final hits = await kb.search(
  vector: queryEmbedding,
  text: 'on-device database',
  filter: Filter.eq('lang', 'en'),
  k: 5,
);
await kb.close();

Retrieval-augmented generation, embeddings and LLM clients live in package:phoenixdb/ai.dart.

Scans, batches and maintenance

db.writeBatch((b) => b
  ..put(utf8Key('user:1'), utf8Value('ada'))
  ..put(utf8Key('user:2'), utf8Value('grace')));   // atomic
for (final e in db.entries(prefix: utf8Key('user:'))) {
  print('${e.keyString} = ${e.valueString}');     // lazily paged
}
db.backup('snapshot.pdb');                        // consistent + compact
print(db.stats());

Limits

Keys are capped at 1 MiB and values at 10 MiB by the FFI layer; the B+Tree additionally caps keys at 1 KiB so a node always holds several entries. Large values spill onto overflow pages transparently. Vectors are capped at 65 536 dimensions and their ids at 128 bytes.

Classes

AsyncPhoenixCollection
Asynchronous PhoenixCollection backed by a supervised worker isolate.
AsyncPhoenixDB
Asynchronous PhoenixDB client backed by a dedicated worker isolate.
AsyncPhoenixVectorDB
Asynchronous vector-search client backed by a dedicated worker isolate.
Change
One committed change to a key.
ChangeWatcher
A subscription to committed changes. Close it when done.
CollectionChange
One committed change to a document in a collection.
CollectionQuery
A collection search; see PhoenixCollection.search.
CollectionReport
What PhoenixCollection.verify found.
CollectionStats
Collection statistics.
CollectionWatcher
A subscription to a collection's document changes; close it when done.
Document
One document: an id plus any of text, metadata and an embedding.
DocumentStore
The collection operations the AI toolkit builds on, implemented by AsyncPhoenixCollection directly and by PhoenixCollection.asStore.
Filter
A metadata filter, MongoDB style. Combine with &, | and ~.
Fusion
How vector and keyword rankings combine in a hybrid search.
PhoenixCollection
A synchronous handle to a document collection.
PhoenixDatabase
A synchronous handle to an open PhoenixDB database.
PhoenixEntry
One key/value pair returned by a scan.
PhoenixOptions
Engine options applied when a database is opened.
PhoenixPrefs
A typed, async key/value store with a SharedPreferencesAsync-shaped API.
PhoenixStats
Runtime statistics of an open database.
PhoenixStatus
Status codes returned by every phoenix_* entry point.
PhoenixTreeReport
Result of a full structural check of the B+Tree.
PhoenixVectorDB
A synchronous handle to an open vector index.
PrefCodec
Encodes and decodes tagged preference values.
SalvageReport
What PhoenixDatabase.salvage recovered from a damaged file.
SearchHit
One search result.
SqlResult
The outcome of one SQL statement.
TraceSpan
One engine span recorded while tracing was enabled.
VectorMatch
One search result.
VectorQuery
A k-NN query.
VectorStats
Live, total and deleted record counts.
WriteBatch
A set of writes applied atomically by write.

Enums

ChangeKind
What happened to a key or document.
PrefType
On-disk type tags. The tag is the first byte of every encoded value.
VectorMetric
Similarity metric used to order neighbours.

Constants

kExpectedAbiVersion → const int
ABI version this Dart package was written against.

Functions

prefixSuccessor(Uint8List prefix) → Uint8List?
Smallest key greater than every key starting with prefix, or null when there is none (an empty prefix, or one made only of 0xFF bytes).
utf8Decode(Uint8List bytes) → String
Decodes UTF-8 bytes back into a string.
utf8Key(String s) → Uint8List
Encodes s as UTF-8 bytes for use as a key.
utf8Value(String s) → Uint8List
Encodes s as UTF-8 bytes for use as a value.

Exceptions / Errors

KeyNotFoundException
Thrown specifically when a key is missing, so callers can catch it narrowly.
PhoenixDecodeException
Thrown when stored bytes cannot be decoded as the type their tag claims.
PhoenixException
Thrown when a native call fails.
PhoenixLoadException
Thrown when the native library cannot be located or is incompatible.
PhoenixTypeMismatch
Thrown when a key is read with an accessor that does not match the type it was written with.