AcornDB 0.1.0
See the version list below for details.
dotnet add package AcornDB --version 0.1.0
NuGet\Install-Package AcornDB -Version 0.1.0
<PackageReference Include="AcornDB" Version="0.1.0" />
<PackageVersion Include="AcornDB" Version="0.1.0" />
<PackageReference Include="AcornDB" />
paket add AcornDB --version 0.1.0
#r "nuget: AcornDB, 0.1.0"
#:package AcornDB@0.1.0
#addin nuget:?package=AcornDB&version=0.1.0
#tool nuget:?package=AcornDB&version=0.1.0
π° AcornDB

AcornDB is a lightweight, reactive, embedded database for .NET β for devs whoβd rather ship products than pay $400/month to store 5MB of JSON.
πΏοΈ Nutty by design. Practical by necessity.
π Why AcornDB Exists
Most apps donβt need Cosmos DB, Kafka, or Redis.
They need:
- Fast, local-first persistence
- Simple per-tenant or per-user storage
- Offline support + syncing that doesnβt make you cry
AcornDB is for:
- Desktop apps
- IoT devices
- Mobile backends
- CLI tools
- Serverless & edge workloads
- And yes β you with the single-user SaaS that stores 10KB per user
π Core Concepts
| Term | What It Means |
|---|---|
Tree<T> |
A local document collection β your "embedded table" |
NutShell<T> |
An object wrapped with metadata (TTL, version, timestamp) |
ITrunk<T> |
Storage abstraction: File, Memory, Azure Blob, or versioned |
Branch |
A connection to a remote Tree via HTTP |
Tangle |
A live sync session between two Trees |
Grove |
A set of Trees managed + synced together |
Canopy |
(Internal) sync orchestrator living inside the Grove |
Stash/Crack/Toss |
Insert, read, and delete objects β squirrel-style verbs |
Shake() |
Manual sync trigger |
π§ Features
| Feature | Description |
|---|---|
π° Stash, Crack, Toss |
Drop-in persistence with zero boilerplate |
π‘οΈ NutShell<T> |
Versioned, timestamped, TTL-wrapped records |
π Branch, Tangle, Grove |
Live sync between Trees, across machines |
πͺ’ Entangle<T>() |
Automatically starts syncing on stash/toss |
π© Oversee<T>() |
One-liner to monitor remote branches |
βοΈ Squabble() + Judge |
Built-in conflict resolution with custom override |
π§ INutment<TKey> |
Typed ID interface for strongly keyed documents |
π§Ή SmushNow() |
Manual compaction of log-based storage |
π°οΈ ExportChanges() / ImportChanges() |
Manual sync if youβre old-school |
π² Grove.Plant<T>() |
Auto-creates and registers a Tree<T> |
| π Totem-based auth (coming) | Because why not woodland-themed security? |
π§ͺ Getting Started
# Coming soon to NuGet:
dotnet add package AcornDB
// Create a Tree and stash some data
var tree = new Tree<User>();
tree.Stash("abc", new User { Name = "Squirrelius Maximus" });
// Set up syncing with a Grove
var grove = new Grove();
grove.Plant(tree);
grove.Oversee<User>(new Branch("http://localhost:5000")); // auto-sync!
tree.Shake(); // optionally force a sync
ποΈ Storage Abstraction (Trunks)
AcornDB uses Trunks to abstract storage β swap your backend without touching your Tree code.
Available Trunks
| Trunk | Use Case | History | Sync |
|---|---|---|---|
FileTrunk<T> |
Simple file-based storage | β | β |
MemoryTrunk<T> |
Fast in-memory (great for tests) | β | β |
DocumentStoreTrunk<T> |
Full versioning & time-travel | β | β |
AzureTrunk<T> |
Azure Blob Storage | β | β |
Examples
// π FileTrunk: Simple, no history
var fileTree = new Tree<User>(new FileTrunk<User>("data/users"));
fileTree.Stash("alice", new User("Alice"));
// πΎ MemoryTrunk: Fast, non-durable
var memTree = new Tree<User>(new MemoryTrunk<User>());
memTree.Stash("bob", new User("Bob"));
// π DocumentStoreTrunk: Full history & versioning
var docTree = new Tree<User>(new DocumentStoreTrunk<User>("data/versioned"));
docTree.Stash("charlie", new User("Charlie v1"));
docTree.Stash("charlie", new User("Charlie v2"));
var history = docTree.GetHistory("charlie"); // Get previous versions!
// Returns: 1 previous version ("Charlie v1")
// π Export/Import between trunks
var sourceTrunk = new FileTrunk<User>("data/source");
var targetTrunk = new AzureTrunk<User>("connection-string");
targetTrunk.ImportChanges(sourceTrunk.ExportChanges()); // Migrate!
Time-Travel with DocumentStoreTrunk
var trunk = new DocumentStoreTrunk<Product>("data/products");
var tree = new Tree<Product>(trunk);
tree.Stash("widget", new Product("Widget v1.0"));
tree.Stash("widget", new Product("Widget v2.0"));
tree.Stash("widget", new Product("Widget v3.0"));
var current = tree.Crack("widget"); // "Widget v3.0"
var history = tree.GetHistory("widget"); // ["Widget v1.0", "Widget v2.0"]
// All changes stored in append-only log: data/products/changes.log
NotSupportedException Pattern
Trunks that don't support history throw NotSupportedException:
var memTree = new Tree<User>(new MemoryTrunk<User>());
try {
var history = memTree.GetHistory("user1");
} catch (NotSupportedException) {
Console.WriteLine("MemoryTrunk doesn't support history!");
}
Feature Detection with ITrunkCapabilities
Check trunk features without exceptions:
var trunk = new MemoryTrunk<User>();
var caps = trunk.GetCapabilities();
Console.WriteLine($"Trunk: {caps.TrunkType}");
Console.WriteLine($"History: {caps.SupportsHistory}");
Console.WriteLine($"Sync: {caps.SupportsSync}");
Console.WriteLine($"Durable: {caps.IsDurable}");
Console.WriteLine($"Async: {caps.SupportsAsync}");
// Use extension methods for quick checks
if (trunk.CanGetHistory())
{
var history = trunk.GetHistory("user1");
}
else
{
Console.WriteLine("This trunk doesn't support history");
}
Capability Matrix:
| Trunk | History | Sync | Durable | Async |
|---|---|---|---|---|
| FileTrunk | β | β | β | β |
| MemoryTrunk | β | β | β | β |
| DocumentStoreTrunk | β | β | β | β |
| AzureTrunk | β | β | β | β |
π Sync with TreeBark
TreeBark is the HTTP sync server for AcornDB - it exposes Trees over REST endpoints.
Quick Start Sync Server
// Server side (AcornSyncServer project)
var grove = new Grove();
grove.Plant(new Tree<User>(new FileTrunk<User>("data/users")));
grove.Plant(new Tree<Product>(new FileTrunk<Product>("data/products")));
// Run with: dotnet run --project AcornSyncServer
// TreeBark starts on http://localhost:5000
TreeBark REST API
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Health check + API docs |
/bark/{treeName}/stash |
POST | Stash a nut to remote tree |
/bark/{treeName}/crack/{id} |
GET | Crack a nut from remote tree |
/bark/{treeName}/toss/{id} |
DELETE | Toss a nut from remote tree |
/bark/{treeName}/export |
GET | Export all nuts from tree |
/bark/{treeName}/import |
POST | Import nuts into tree |
Client-Side Sync with Branch
// Client side - connect to remote TreeBark server
var localTree = new Tree<User>(new MemoryTrunk<User>());
var branch = new Branch("http://localhost:5000/bark/User");
// Manual push
localTree.Stash("alice", new User("Alice"));
branch.TryPush("alice", localTree.Crack("alice"));
// Manual pull
await branch.ShakeAsync(localTree); // Pulls all remote changes
// Auto-sync with Tangle
var grove = new Grove();
grove.Plant(localTree);
grove.Entangle<User>(branch, "sync-session-1"); // Auto-syncs on every stash!
Full Sync Example
Server (dotnet run --project AcornSyncServer):
var grove = new Grove();
grove.Plant(new Tree<User>(new DocumentStoreTrunk<User>("data/users")));
// TreeBark running on http://localhost:5000
Client 1 (Desktop App):
var tree1 = new Tree<User>(new FileTrunk<User>("client1/users"));
var branch = new Branch("http://localhost:5000");
tree1.Stash("alice", new User("Alice"));
branch.TryPush("alice", tree1.Crack("alice")); // Syncs to server
Client 2 (Mobile App):
var tree2 = new Tree<User>(new MemoryTrunk<User>());
var branch = new Branch("http://localhost:5000");
await branch.ShakeAsync(tree2); // Pulls "alice" from server!
var alice = tree2.Crack("alice"); // "Alice" is now local
π° AcornDB Visualizer - Web UI
Explore your Grove with an interactive web dashboard!
cd AcornVisualizer
dotnet run
# Open browser to http://localhost:5100
Features:
- π Live Dashboard - Real-time stats on trees, nuts, and operations
- π³ Tree Explorer - Browse all trees with detailed metadata
- π Graph View - Interactive circular node visualization
- π Nut Inspector - View payloads, timestamps, and history
- βοΈ Trunk Info - See capabilities (history, sync, durable, async)
- π Auto-Refresh - Updates every 5 seconds
Perfect for:
- Local development and debugging
- Visual demos and presentations
- Understanding your grove structure
- Monitoring nut operations
See AcornVisualizer/README.md for full documentation.
π² P2P File System Sync (Same Host)
For same-host multi-process scenarios, AcornDB supports file system-based peer-to-peer sync without needing a server!
How It Works
Instead of HTTP, processes sync via a shared directory:
Process 1 (data/process1) βββ
ββββΊ Sync Hub (data/sync-hub)
Process 2 (data/process2) βββ
Each process:
- Maintains its own local
DocumentStoreTrunk - Exports changes to the shared sync hub
- Imports changes from other processes
- Resolves conflicts via timestamp comparison
Example: Two Processes on Same Host
Process 1:
var localTree = new Tree<User>(new DocumentStoreTrunk<User>("data/process1/users"));
var syncHub = new FileSystemSyncHub<User>("data/sync-hub");
localTree.Stash("alice", new User { Name = "Alice" });
// Export to hub
syncHub.PublishChanges("process1", localTree.ExportChanges());
Process 2:
var localTree = new Tree<User>(new DocumentStoreTrunk<User>("data/process2/users"));
var syncHub = new FileSystemSyncHub<User>("data/sync-hub");
// Import from hub
var changes = syncHub.PullChanges("process2");
foreach (var shell in changes)
{
localTree.Stash(shell.Id, shell.Payload);
}
// Process 2 now has Alice!
Try the Demo
# Terminal 1
cd SyncDemo
run-demo.cmd 1
# Terminal 2
cd SyncDemo
run-demo.cmd 2
Watch changes sync between processes in real-time via the file system!
When to Use File-Based vs HTTP Sync
| Scenario | Recommended Approach |
|---|---|
| Same host, multiple processes | π’ File-based P2P |
| Different hosts | π’ TreeBark HTTP |
| Desktop apps with multiple instances | π’ File-based P2P |
| Mobile to cloud | π’ TreeBark HTTP |
| Distributed systems | π’ TreeBark HTTP |
| CLI tools | π’ File-based P2P |
π§± Project Structure
| Folder | Purpose |
|---|---|
AcornDB |
Core engine (Tree, NutShell, Trunk, Tangle) |
AcornSyncServer |
TreeBark: HTTP sync server (REST API) |
AcornVisualizer |
Web UI: Interactive grove dashboard |
AcornDB.Canopy |
SignalR hub + visualizations |
AcornDB.Demo |
Examples showcasing all features |
SyncDemo |
Live multi-client sync demonstration |
AcornDB.Test |
xUnit tests (26 passing) |
π§ What's Coming
- π Auth: Totems, ForageRights, Critters, and BarkCodes
- π‘ Mesh sync: Peer-to-peer Tangle networks
- π¦ NuGet & CLI: Install and create projects with
acorn new - π AutoRecovery: Offline-first sync queue with resilience
- π§ͺ Playgrounds: Sample apps, code snippets, and demos
- π¨ Visualizer Enhancements: Real-time updates, diff viewer, dark mode
π² The Acorn Ethos
πΏοΈ Serious software. Zero seriousness.
AcornDB was born out of frustration with bloated infra, soulless APIs, and naming things like DataClientServiceManagerFactoryFactory.
So we built something better β not just in function, but in vibe.
We believe:
- Developers deserve fun.
- Tools should make you smile, not sigh.
- Syncing JSON should not require Kubernetes and a degree in wizardry.
- "Toss the nut and shake the tree" should be valid engineering advice.
If youβve ever rage-quit YAML, yelled at Terraform, or cried syncing offline-first apps β
welcome. Youβve found your grove.
π° Stash boldly. Crack with confidence. And never, ever apologize for getting a little squirrelly.
𦦠Built with acorns and sarcasm
Weβre tired of YAML. Tired of cloud bills. Tired of DataServiceFactoryClientFactoryFactory.
So we built AcornDB.
If you fork this, star it, or build something fun β send us your weirdest squirrel pun.
πΏοΈ Stay nutty.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Azure.Storage.Blobs (>= 12.19.1)
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.0.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on AcornDB:
| Package | Downloads |
|---|---|
|
AcornDB.Canopy
🌲 AcornDB.Canopy - SignalR hub and real-time visualization extensions for AcornDB. Adds Hardwood HTTP server, live sync orchestration, and real-time grove monitoring capabilities. |
|
|
AcornDB.Persistence.Cloud
🌰 Cloud storage providers for AcornDB - AWS S3, Azure Blob Storage, and other cloud-based trunk implementations. Separate package to keep core AcornDB lean. |
|
|
AcornDB.Persistence.RDBMS
🌰 RDBMS storage providers for AcornDB - SQLite, SQL Server, PostgreSQL, MySQL trunk implementations for relational database persistence. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release with core features: Tree, NutShell, Trunk abstraction, file/memory/document storage, and sync capabilities.