SNKV is a lightweight, high‑performance ACID compliant key–value store built directly on top of the SQLite v3.51.200 B‑Tree layer.
Instead of using SQLite through SQL queries, SNKV bypasses the entire SQL processing stack and directly invokes SQLite’s production‑ready B‑Tree APIs to perform key–value operations.
The result is a database that retains SQLite’s proven reliability and durability, while being ~60% faster for mixed KV workloads (70% read, 20% write, 10% delete operations) due to dramatically reduced overhead.
SQLite is an excellent general‑purpose database, but for key–value workloads it carries significant overhead:
- SQL parsing and compilation
- Virtual machine execution (VDBE)
- Query optimization and schema management
SNKV removes these layers entirely and keeps only what is essential for a KV store.
SNKV builds as a static library (libsnkv.a):
make # builds libsnkv.a
make examples # builds example programs in examples/
make run-examples # builds and runs all examples
make test # runs all test suites
make clean # removes all build artifacts
SNKV exposes a simple C API for key–value operations without any SQL involvement.
#include "kvstore.h"
int main(void) {
KVStore *pKV;
kvstore_open("mydb.db", &pKV, 0, KVSTORE_JOURNAL_WAL);
kvstore_put(pKV, "key", 3, "value", 5);
void *pValue; int nValue;
kvstore_get(pKV, "key", 3, &pValue, &nValue);
printf("%.*s\n", nValue, (char*)pValue);
sqliteFree(pValue);
kvstore_close(pKV);
return 0;
}
Compile against the library:
gcc -Iinclude -o myapp myapp.c libsnkv.a
Standalone examples are provided in the examples/ directory:
| Example | Covers |
|---|---|
examples/basic.c |
Hello world, CRUD, existence checks |
examples/transactions.c |
Atomic batch operations, rollback |
examples/column_families.c |
Data organization with column families |
examples/iterators.c |
Scanning, filtered iteration, statistics |
examples/session_store.c |
Real-world session management |
examples/benchmark.c |
Auto-commit vs batch transaction performance |
See kvstore_example.md for the full API usage guide.
- ACID transactions — begin, commit, rollback with full durability
- WAL mode — Write-Ahead Logging for concurrent readers + writer
- Column families — multiple logical namespaces in a single database
- Iterators — ordered key-value traversal with cursor-based scanning
- Thread safety — mutex-protected operations for concurrent access
- Zero memory leaks — verified with Valgrind memcheck
All unit tests and benchmarks are located in the tests/ directory (8 test suites, 100+ tests).
┌─────────────────────────────────────────────────────────────────────────────┐
│ The Stack We REMOVED │
└─────────────────────────────────────────────────────────────────────────────┘
REMOVED from SQLite Why It's Not Needed for SNKV
═══════════════════════ ═══════════════════════════
┌──────────────────────────┐
│ SQL Interface Layer │ No SQL → Not required
│ - sqlite3_prepare() │
│ - sqlite3_step() │
│ - sqlite3_bind_*() │
└──────────────────────────┘
│
▼
┌──────────────────────────┐
│ SQL Compiler │ No SQL → No parsing or codegen
│ - Tokenizer │
│ - Parser │
│ - Code Generator │
└──────────────────────────┘
│
▼
┌──────────────────────────┐
│ Virtual Machine │ No bytecode execution
│ - VDBE Executor │
│ - Opcode Interpreter │
│ - 200+ opcodes │
└──────────────────────────┘
│
▼
┌──────────────────────────┐
│ Backend Layer │ No schema or query planning
│ - Query Optimizer │
│ - Index Manager │
│ - Schema Manager │
└──────────────────────────┘
│
▼
═══════════════════════════════════════════════════
SNKV intentionally keeps the most battle‑tested parts of SQLite, unchanged:
┌──────────────────────────┐ ┌──────────────────────────┐
│ B-Tree Engine │ ══════════▶ │ B-Tree Engine │
│ (SQLite proven code) │ KEPT THIS │ (Same proven code) │
└──────────────────────────┘ └──────────────────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ Pager Module │ ══════════▶ │ Pager Module │
│ (Cache, Journaling) │ KEPT THIS │ (Same code) │
└──────────────────────────┘ └──────────────────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ OS Interface │ ══════════▶ │ OS Interface │
│ (File I/O, Locks) │ KEPT THIS │ (Same code) │
└──────────────────────────┘ └──────────────────────────┘
This means SNKV benefits from:
- Crash safety (rollback journal and WAL)
- Atomic commits
- Page cache and efficient I/O
- Write-Ahead Logging for concurrent access
- Real‑world tested
┌────────────────┐
│ Application │
└────────┬───────┘
│
│ kvstore_put(key, value)
│ kvstore_get(key) → value
│ kvstore_delete(key)
│ kvstore_begin(), kvstore_commit(), kvstore_rollback(), ...
▼
┌────────────────────────────────┐
│ KVStore Layer │
│ (Thin Wrapper - ~2400 LOC) │
│ │
│ • Simple API │
│ • Column Families │
│ • Thread Safety (Mutexes) │
│ • Validation │
│ • Statistics │
└────────────┬───────────────────┘
│
│ Direct calls (no SQL!)
│
▼
┌────────────────────────────────┐
│ B-Tree Engine │
│ (SQLite v3.51.200 - Proven Code) │
│ │
│ • Tree Operations │
│ • Key-Value Storage │
│ • Cursors & Navigation │
└────────────┬───────────────────┘
│
│
▼
┌────────────────────────────────┐
│ Pager Module │
│ (SQLite v3.51.200 - Proven Code) │
│ │
│ • Transaction Management │
│ • Rollback Journal │
│ • ACID Guarantees │
└────────────┬───────────────────┘
│
│
▼
┌────────────────────────────────┐
│ OS Interface │
│ (SQLite v3.51.200 - Proven Code) │
│ │
│ • File I/O │
│ • File Locking │
│ • Crash Recovery │
└────────────┬───────────────────┘
│
│
▼
┌──────────────┐
┌──────────────┐
│ Disk Files │
│ │
│ • kvstore.db│
│ • -wal │
│ • -shm │
│ • -journal │
└──────────────┘
Same reliability, fewer layers, significantly faster KV performance.
- No SQL parsing or planning
- No virtual machine execution
- Direct B‑Tree access
Typical gains:
- Lower memory usage
- Predictable latency
The following table shows the average performance across 5 runs for both SQLite v3.51.200 (SQL-based KV access) and SNKV (direct B-Tree KV access) using identical workloads (50,000 records).
All numbers are operations per second (ops/sec).
| Benchmark | SQLite (avg) | SNKV (avg) | Winner |
|---|---|---|---|
| Sequential Writes | 146,727 | 128,310 | SQLite (+14%) |
| Random Reads | 173,863 | 219,050 | SNKV (+26%) |
| Sequential Scan | 2,138,485 | 3,025,534 | SNKV (~1.4×) |
| Random Updates | 116,026 | 111,054 | Tie |
| Random Deletes | 62,728 | 105,890 | SNKV (+69%) |
| Exists Checks | 263,348 | 227,897 | SQLite (+16%) |
| Mixed Workload (70R/20W/10D) | 129,999 | 210,916 | SNKV (+62%) |
| Bulk Insert (single txn) | 245,598 | 269,433 | SNKV (+10%) |
- SNKV dominates mixed and delete-heavy workloads due to zero SQL/VDBE overhead
- Random reads are 26% faster in SNKV — no SQL parsing or statement preparation per lookup
- Sequential scans are ~1.4× faster in SNKV due to direct cursor traversal
- Deletes are 69% faster — the biggest single-operation win for SNKV
- SQLite wins sequential writes and exists checks due to its optimized prepared-statement caching
- Update performance is effectively identical (same B-Tree + Pager path)
SNKV is ideal for:
- Embedded systems
- Low‑memory environments
- Configuration stores
- Metadata databases
- C/C++ applications needing fast KV access
- Systems that do not need SQL
- Many more
If you need joins, ad‑hoc queries, or analytics — use SQLite.
If you need fast, reliable key–value storage — use SNKV.
SNKV proves a simple idea:
If you don’t need SQL, don’t pay for it.
By standing directly on SQLite’s B‑Tree engine, SNKV delivers a focused, fast, and reliable key–value database with minimal complexity.
Copyright © 2025 Hash Anu
Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this project except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.