{"id":33091512,"url":"https://github.com/ankur-anand/unisondb","last_synced_at":"2026-01-14T21:22:03.242Z","repository":{"id":275478031,"uuid":"926191450","full_name":"ankur-anand/unisondb","owner":"ankur-anand","description":"A streaming multimodal database for Edge AI, and Edge Computing.","archived":false,"fork":false,"pushed_at":"2026-01-04T15:40:19.000Z","size":3096,"stargazers_count":386,"open_issues_count":5,"forks_count":14,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-01-05T22:16:16.534Z","etag":null,"topics":["ai-agents","database","edge-computing","go","golang","golang-database","grpc","grpc-go","key-value","multi-modal","replicated","row-column","streaming","streaming-data","streaming-database","unisondb","wide-column-database"],"latest_commit_sha":null,"homepage":"https://unisondb.io/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ankur-anand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-02T19:05:51.000Z","updated_at":"2026-01-04T15:40:21.000Z","dependencies_parsed_at":"2025-03-28T06:22:44.788Z","dependency_job_id":"f3fc6317-8762-4a56-9614-459b5f0e773d","html_url":"https://github.com/ankur-anand/unisondb","commit_stats":null,"previous_names":["ankur-anand/kvreplicator","ankur-anand/kvalchemy","ankur-anand/unisondb"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ankur-anand/unisondb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankur-anand%2Funisondb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankur-anand%2Funisondb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankur-anand%2Funisondb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankur-anand%2Funisondb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ankur-anand","download_url":"https://codeload.github.com/ankur-anand/unisondb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankur-anand%2Funisondb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28434836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","database","edge-computing","go","golang","golang-database","grpc","grpc-go","key-value","multi-modal","replicated","row-column","streaming","streaming-data","streaming-database","unisondb","wide-column-database"],"created_at":"2025-11-14T18:00:27.835Z","updated_at":"2026-01-14T21:22:03.231Z","avatar_url":"https://github.com/ankur-anand.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"## UnisonDB\n\n\u003e Store, stream, and sync instantly — **UnisonDB** is a **log-native, real-time database** that replicates like a **message bus for AI and Edge Computing**.\n\n\u003cimg src=\"docs/logo.svg\" width=\"300\" alt=\"UnisonDB\" /\u003e\n\n[![ci-tests](https://github.com/ankur-anand/unisondb/actions/workflows/go.yml/badge.svg)](https://github.com/ankur-anand/unisondb/actions/workflows/go.yml)\n[![Coverage Status](https://coveralls.io/repos/github/ankur-anand/unisondb/badge.svg?branch=main)](https://coveralls.io/github/ankur-anand/unisondb?branch=main)\n[![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)\n[![Docs](https://img.shields.io/badge/UnisonDB-Getting%20Started-0b5fff?style=flat-square)](https://unisondb.io/docs/getting-started/)\n[![Status: Alpha](https://img.shields.io/badge/status-alpha-orange)](#)\n\n## What UnisonDB Is\n\nUnisonDB is an open-source database designed specifically for [**Edge AI**](https://www.ibm.com/think/topics/edge-ai) and [**Edge Computing**](https://en.wikipedia.org/wiki/Edge_computing).  \n\nIt is a **reactive**, [**log-native**](https://www.unisondb.io/docs/architecture/) and [**multi-model database**](https://en.wikipedia.org/wiki/Multi-model_database) built for real-time and edge-scale applications.  UnisonDB combines a [**B+Tree storage engine**](https://en.wikipedia.org/wiki/B%2B_tree) with WAL-based ([**Write-Ahead Logging**](https://en.wikipedia.org/wiki/Write-ahead_logging)) streaming replication, enabling near-instant fan-out replication across hundreds of nodes — all while preserving strong consistency and durability.\n\n## Key Features\n- **Multi-Modal Storage**: Key-Value, Wide-Column, and Large Objects (LOB)\n- **Streaming Replication**: WAL-based replication with sub-second fan-out to 100+ edge replicas\n- **Real-Time Notifications**: ZeroMQ-based(Side-car) change notifications with sub-millisecond latency\n- **Durable**: B+Tree storage with Write-Ahead Logging\n- **Edge-First Design**: Optimized for edge computing and local-first architectures\n- **Namespace Isolation**: Multi-tenancy support with namespace-based isolation\n\n![storage architecture](docs/unisondb_overview.png)\n\n## Use Cases\n\nUnisonDB is built for **distributed edge-first architectures** systems where **data and computation must live close together** — reducing network hops, minimizing latency, and enabling real-time responsiveness at scale.\n\nBy **co-locating data with the services that use it**, UnisonDB removes the traditional boundary between the database and the application layer.\nApplications can react to local changes instantly, while UnisonDB’s WAL-based replication ensures eventual consistency across all replicas globally.\n\n## Fan-Out Scaling\n\nUnisonDB can fan out updates to 100+ edge nodes in just a few milliseconds from a single upstream—and because it supports multi-hop relaying, \nthat reach compounds naturally. Each hop carries the network + application latency of its link;\n\nIn a simple 2-hop topology:\n- **Hop 1:** Primary → 100 hubs (≈250–500ms)\n- **Hop 2:** Each hub → 100 downstream edge nodes (similar latency)\n- **Total reach:** 100 + 10,000 = 10,100 nodes\n\nEven at 60k–80k `SET` ops/sec with 1 KB values, UnisonDB can propagate those updates across 10,000+ nodes within seconds—without Kafka, Pub/Sub, CDC pipelines, or heavyweight brokers. (See the [Relayer vs Latency benchmarks](#performance-testing-local-replication) below for measured numbers.)\n\n## Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/ankur-anand/unisondb\ncd unisondb\n\n# Build\ngo build -o unisondb ./cmd/unisondb\n\n# Run in server mode (primary)\n./unisondb server --config config.toml\n\n# Use the HTTP API\ncurl -X PUT http://localhost:4000/api/v1/default/kv/mykey \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"value\":\"bXl2YWx1ZQ==\"}'\n```\n\n## Documentation\n\n1. [Getting Started with UnisonDB](https://unisondb.io/docs/getting-started/)\n2. [Complete Configuration Guide](https://unisondb.io/docs/getting-started/configurations/)\n3. [Architecture Overview](https://unisondb.io/docs/architecture/)\n4. [HTTP API Reference](https://unisondb.io/docs/api/http-api/)\n5. [Backup and Restore](https://unisondb.io/docs/operations/backup-restore/)\n6. [Deployment Topologies](https://unisondb.io/docs/deployment/)\n7. [Rough Roadmap](https://github.com/ankur-anand/unisondb/wiki/Roadmap)\n\nUnisonDB implements a pluggable storage backend architecture supporting two BTree implementations:\n  - [BoltDB](https://github.com/etcd-io/bbolt): Single-file, ACID-compliant BTree.\n  - [LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database): Memory-mapped ACID-compliant BTree with copy-on-write semantics.\n\n## Redis-Compatible Benchmark: UnisonDB vs BadgerDB vs BoltDB vs LMDB\n\nThis benchmark compares the **write and read performance** of four databases — **UnisonDB**, **BadgerDB**, *LMDB** and **BoltDB** — using a Redis-compatible interface and the official [`redis-benchmark`](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/benchmarks/) tool.\n\n### What We Measured\n\n- **Throughput**: Requests per second for `SET` (write) and `GET` (read) operations\n- **Latency**: p50 latency in milliseconds\n- **Workload**: 50 iterations of mixed `SET` and `GET` operations (200k ops per run)\n- **Concurrency**: 10 parallel clients, 10 pipelined requests, 4 threads\n- **Payload Size**: 1KB\n\n### Test Environment\n\n```\nChip: Apple M2 Pro\nTotal Number of Cores: 10 (6 performance and 4 efficiency)\nMemory: 16 GB\nUnisondb Btree Backend - LMDB\n```\n\nAll three databases were tested under identical conditions to highlight differences in write path efficiency, read performance, and I/O characteristics. The Redis-compatible server implementation can be found in `internal/benchtests/cmd/redis-server/`.\n\n\n### Results\n\n\u003cimg src=\"docs/ubbl_compare.png\" alt=\"UnisonDB, BadgerDB, BoltDB, LMDB Comparison\" /\u003e\n\n## Performance Testing: Local Replication\n\n### Test Setup\n\nWe validated the WAL-based replication architecture using the `pkg/replicator` component. It Uses the same redis-compatible\nbench tool but this time the server is started a `n=[100,200,500,750,1000]` goroutine that is an independent WAL reader, capturing critical performance metrics:\n\n1. Physical Latency Tracking: Measures p50, p90, p99, and max latencies Vs Relayer.\n2. SET, GET Latency vs Relayer\n3. SET, GET Throughput Vs Relayer.\n\n### Results\n\n\n\u003cimg src=\"docs/relayer_set_get.png\" alt=\"relayer_set_get\" /\u003e \n\u003cimg src=\"docs/relayer_latency_granular.png\" alt=\"relayer_latency_granular\" /\u003e\n\n### Test Replication Flow\n\n\u003cimg src=\"./docs/replication_test.png\"\u003e\n\n---\n\n## Why UnisonDB\n\n\u003e Traditional databases persist. Stream systems propagate.\nUnisonDB does both — turning every write into a durable, queryable stream that replicates seamlessly across the edge.\n\n### The Problem: Storage and Streaming Live in Different Worlds\n\nModern systems are reactive — every change needs to **propagate instantly** to dashboards, APIs, caches, and edge devices.  \nYet, databases were built for persistence, not propagation.\n\nYou write to a database, then stream through Kafka.  \nYou replicate via CDC.  \nYou patch syncs between cache and storage.\n\nThis split between **state and stream** creates friction:\n- Two systems to maintain and monitor\n- Eventual consistency between write path and read path\n- Network latency on every read or update\n- Complex fan-out when scaling to hundreds of edges\n\n---\n\n### The Gap\n\n**LMDB** and **BoltDB** excel at local speed — but stop at one node.  \n**etcd** and **Consul** replicate state — but are consensus-bound and small-cluster only.  \n**Kafka** and **NATS** stream messages — but aren’t queryable databases.\n\n| System | Strength | Limitation |\n|---------|-----------|-------------|\n| LMDB / BoltDB | Fast local storage | No replication |\n| etcd / Consul | Cluster consistency | No local queries, low fan-out |\n| Kafka / NATS | Scalable streams | No storage or query model |\n\n---\n\n### The Solution: Log-Native by Design\n\nUnisonDB fuses **database semantics** with **streaming mechanics** — the log *is* the database.  \nEvery write is durable, ordered, and instantly available as a replication stream.\n\nNo CDC, no brokers, no external pipelines.  \nJust one unified engine that:\n\n- Stores data in **B+Trees** for predictable reads\n- Streams data via **WAL replication** to thousands of nodes\n- Reacts instantly with **sub-second fan-out**\n- Keeps local replicas fully queryable, even offline\n\nUnisonDB eliminates the divide between “database” and “message bus,”  \nenabling **reactive, distributed, and local-first** systems — without the operational sprawl.\n\n\u003e **UnisonDB collapses two worlds — storage and streaming — into one unified log-native core.**  \n\u003e The result: a single system that stores, replicates, and reacts — instantly.\n\n---\n\n## Core Architecture \n\nUnisonDB is built on three foundational layers:\n\n1. **WALFS** - Write-Ahead Log File System (mmap-based, optimized for reading at scale).\n2. **Engine** - Hybrid storage combining WAL, MemTable, and B-Tree\n3. **Replication** - WAL-based streaming with offset tracking\n\n## The Layered View\n\nUnisonDB stacks a multi-model engine on top of WALFS — a log-native core that unifies storage, replication, and streaming into one continuous data flow.\n\n```\n+-----------------------------------------------------------+\n|                Multi-Model API Layer                      |\n|       (KV, Wide-Column, LOB, Txn Engine, Query)           |\n+-----------------------------------------------------------+\n|                   Engine Layer                            |\n|   WALFS-backed MemTable + B-Tree Store                    |\n|   (writes → WALFS, reads → B-Tree + MemTable)             |\n+-----------------------------------------------------------+\n|          WALFS (Core Log)          |  Replication Layer   |\n|  Append-only, mmap-based           |  WAL-based streaming |\n|  segmented log                     |  (followers tail WAL)|\n|  Commit-ordered, replication-safe  |  Offset tracking,    |\n|                                    |  catch-up, tailing   |\n+-----------------------------------------------------------+\n|                       Disk                                |\n+-----------------------------------------------------------+\n```\n\n\n## 1. WALFS (Write-Ahead Log)\n\n### Overview\n\nWALFS is a memory-mapped, segmented write-ahead log implementation designed for **both writing AND reading at scale**. \nUnlike traditional WALs that optimize only for sequential writes, WALFS provides efficient random access for replication, and real-time tailing.\n\n\u003cimg src=\"./docs/walnreader.png\" width=\"500\"\u003e\n\n### Segment Structure\n\nEach WALFS segment consists of two regions:\n\n```\n+----------------------+-----------------------------+-------------+\n|   Segment Header     |        Record 1             |  Record 2   |\n|     (64 bytes)       |  Header + Data + Trailer    |     ...     |\n+----------------------+-----------------------------+-------------+\n```\n\n#### Segment Header (64 bytes)\n\n| Offset | Size | Field           | Description                                  |\n|--------|------|-----------------|----------------------------------------------|\n| 0      | 4    | Magic           | Magic number (`0x5557414C`)                  |\n| 4      | 4    | Version         | Metadata format version                      |\n| 8      | 8    | CreatedAt       | Creation timestamp (nanoseconds)             |\n| 16     | 8    | LastModifiedAt  | Last modification timestamp (nanoseconds)    |\n| 24     | 8    | WriteOffset     | Offset where next chunk will be written      |\n| 32     | 8    | EntryCount      | Total number of chunks written               |\n| 40     | 4    | Flags           | Segment state flags (e.g. Active, Sealed)    |\n| 44     | 12   | Reserved        | Reserved for future use                      |\n| 56     | 4    | CRC             | CRC32 checksum of first 56 bytes             |\n| 60     | 4    | Padding         | Ensures 64-byte alignment                    |\n\n#### Record Format (8-byte aligned)\n\nEach record is written in its own aligned frame:\n\n| Offset  | Size     | Field   | Description                                      |\n|---------|----------|---------|--------------------------------------------------|\n| 0       | 4 bytes  | CRC     | CRC32 of `[Length \\| Data]`                      |\n| 4       | 4 bytes  | Length  | Size of the data payload in bytes                |\n| 8       | N bytes  | Data    | User payload (FlatBuffer-encoded LogRecord)      |\n| 8 + N   | 8 bytes  | Trailer | Canary marker (`0xDEADBEEFFEEEDFACE`)            |\n| ...     | ≥0 bytes | Padding | Zero padding to align to 8-byte boundary         |\n\n### WALFS Reader Capabilities\n\nWALFS provides powerful reading capabilities essential for replication and recovery:\n\n#### 1. **Forward-Only Iterator**\n\n```go\nreader := walLog.NewReader()\ndefer reader.Close()\n\nfor {\n    data, pos, err := reader.Next()\n    if err == io.EOF {\n        break\n    }\n    // Process record\n}\n```\n\n- **Zero-copy reads** - data is a memory-mapped slice\n- **Position tracking** - each record returns its `(SegmentID, Offset)` position\n- **Automatic segment traversal** - seamlessly reads across segment boundaries\n\n#### 2. **Offset-Based Reads**\n\n```go\n// Read from a specific offset (for replication catch-up)\noffset := Offset{SegmentID: 5, Offset: 1024}\nreader, err := walLog.NewReaderWithStart(\u0026offset)\n```\n\n#### Use cases:\n\n* Efficient seek without scanning\n* Follower catch-up from last synced position\n* Recovery from checkpoint\n\n#### 3. **Active Tail Following**\n\n```go\n// For real-time replication (tailing active WAL)\nreader, err := walLog.NewReaderWithTail(\u0026offset)\n\nfor {\n    data, pos, err := reader.Next()\n    if err == ErrNoNewData {\n        // No new data yet, can retry or wait\n        continue\n    }\n}\n```\n#### Behavior:\n\n* Returns ErrNoNewData when caught up (not io.EOF)\n* Enables low-latency streaming\n* Supports multiple parallel readers\n\n### Why WALFS is Different\nUnlike traditional \"write-once, read-on-crash\" WALs, WALFS optimizes for:\n\n* Continuous replication - Followers constantly read from primary's WAL\n* Real-time tailing - Low-latency streaming of new writes\n* Parallel readers - Multiple replicas read concurrently without contention\n\n---\n\n## 2. Engine (dbkernel)\n\n### Overview\n\nThe Engine orchestrates writes, reads, and persistence using three components:\n\n* WAL (WALFS) - Durability and replication source\n* MemTable (SkipList) - In-memory write buffer\n* B-Tree Store - Persistent index for efficient reads\n\n### Flow Diagram\n\n\u003cimg src=\"./docs/engine_flow.png\"\u003e\n\n### FlatBuffer Schema\n\nUnisonDB uses FlatBuffers for zero-copy serialization of WAL records:\n#### Benefits:\n\n* No deserialization on replicas\n* Fast replication\n\n#### Why FlatBuffers?\n\n**Replication efficiency** - No deserialization needed on replicas\n\n\u003cimg src=\"./docs/schema_time.jpg\" width=\"400\"\u003e \u003cimg src=\"./docs/schema_mem.jpg\" width=\"400\"\u003e\n\n### Transaction Support\nUnisonDB provides **atomic multi-key transactions**:\n\n```go\ntxn := engine.BeginTxn()\ntxn.Put(\"k1\", value1)\ntxn.Put(\"k2\", value2)\ntxn.Put(\"k3\", value3)\ntxn.Commit() // All or nothing\n```\n#### Flow\n\n\u003cimg src=\"./docs/txn_flow.png\"\u003e\n\n**Transaction Properties:**\n- **Atomicity** - All writes become visible on commit, or none on abort\n- **Isolation** - Uncommitted writes are hidden from readers\n\n### LOB (Large Object) Support\n\nLarge values can be chunked and streamed using TXN.\n\n#### Flow\n\n\u003cimg src=\"./docs/lob_txn.png\"\u003e\n\n**LOB Properties:**\n- **Transactional** - All chunks committed atomically\n- **Streaming** - Can write/read chunks incrementally\n- **Efficient replication** - Replicas get chunks as they arrive\n\n### Wide-Column Support\n\nUnisonDB supports partial updates to column families:\n\n\u003cimg src=\"./docs/row_cloumn.png\"\u003e\n\n**Benefits:**\n- **Efficient updates** - Only modified columns are written/replicated\n- **Flexible schema** - Columns can be added dynamically\n- **Merge semantics** - New columns merged with existing row\n\n---\n\n## 3. Replication Architecture\n\n### Overview\n\nReplication in UnisonDB is **WAL-based streaming** - designed around the WALFS reader capabilities. Followers continuously stream WAL records from the primary's WALFS and apply them locally.\n\n### Design Principles\n\n1. **Offset-based positioning** - Followers track their replication offset `(SegmentID, Offset)`\n2. **Catch-up from any offset** - Can resume replication from any position\n3. **Real-time streaming** - Active tail following for low-latency replication\n4. **Self-describing records** - FlatBuffer LogRecords are self-contained\n5. **Batched streaming** - Records sent in batches for efficiency\n\n### Replication Flow\n\n* Offset-based positioning - Followers track (SegmentID, Offset) Independently.\n* Catch-up from any offset - Resume from any position\n* Real-time streaming - Active tail following for low latency\n\n\u003cimg src=\"./docs/replication_flow.png\"\u003e\n\n---\n\n\n## Why is Traditional KV Replication Insufficient?\n\n\u003e Most traditional key-value stores were designed for simple, point-in-time key-value operations — and their replication \nmodels reflect that. While this works for basic use cases, it quickly breaks down under real-world \ndemands like multi-key transactions, large object handling, and fine-grained updates.\n\n### Key-Level Replication Only\n\nReplication is often limited to raw key-value pairs. \nThere’s no understanding of higher-level constructs like rows, columns, \nor chunks — making it impossible to efficiently replicate partial updates or large structured objects.\n\n### No Transactional Consistency\n\nReplication happens on a per-operation basis, not as part of an atomic unit.\nWithout multi-key transactional guarantees, systems can fall into inconsistent states across replicas, \nespecially during batch operations, network partitions, or mid-transaction failures.\n\n### Chunked LOB Writes Become Risky\n\nWhen large values are chunked and streamed to the store, traditional replication models expose chunks as they arrive. \nIf a transfer fails mid-way, replicas may store incomplete or corrupted objects, with no rollback or recovery mechanism.\n\n### No Awareness of Column-Level Changes\n\nWide-column data is treated as flat keys or opaque blobs. If only a single column is modified, \ntraditional systems replicate the entire row, wasting bandwidth, \nincreasing storage overhead, and making efficient synchronization impossible.\n\n### Operational Complexity Falls on the User\n\nWithout built-in transactional semantics, developers must implement their own logic for deduplication, \nrollback, consistency checks, and coordination — which adds fragility and complexity to the system.\n\n### Storage Engine Tradeoffs\n\n•\tLSM-Trees (e.g., RocksDB) excel at fast writes but suffer from high read amplification and costly background compactions, which hurt latency and predictability.\n\n•\tB+Trees (e.g., BoltDB,LMDB) offer efficient point lookups and range scans, but struggle with high-speed inserts and lack native replication support.\n \n## How UnisonDB Solves This. :white_check_mark:\n\nUnisonDB combines append-only logs for high-throughput ingest with B-Trees for fast and efficient range reads — while offering:\n\n* Transactional, multi-key replication with commit visibility guarantees.\n* Chunked LOB writes that are fully atomic.\n* Column-aware replication for efficient syncing of wide-column updates.\n* Isolation by default — once a network-aware transaction is started, all intermediate writes are fully isolated and not visible to readers until a successful txn.Commit().\n* Built-in replication via gRPC WAL streaming + B-Tree snapshots.\n* Zero-compaction overhead, high write throughput, and optimized reads.\n\n## Development\n```sh\nmake lint\nmake test\n```\n\n## certificate for Local host\n\n```shell\nbrew install mkcert\n\n## install local CA\nmkcert -install\n\n## Generate gRPC TLS Certificates\n## these certificate are valid for hostnames/IPs localhost 127.0.0.1 ::1\n\nmkcert -key-file grpc.key -cert-file grpc.crt localhost 127.0.0.1 ::1\n\n```\n\n## License\n\n[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=ankur-anand/unisondb\u0026type=date\u0026legend=top-left)](https://www.star-history.com/#ankur-anand/unisondb\u0026type=date\u0026legend=top-left)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fankur-anand%2Funisondb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fankur-anand%2Funisondb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fankur-anand%2Funisondb/lists"}