Preface
I'm introducing SoloDB - an embedded database that delivers ACID compliance, NoSQL flexibility, and SQL compatibility through SQLite's JSONB format. It offers an alternative approach to .NET document databases.
Let me share my experience and show you why SoloDB might be the better choice for your next project.
Why was it created
SoloDB was created to simultaneously address these problems: NoSQL flexibility, SQL compatibility, full filesystem support, and strong ACID guarantees.
While excellent databases like LiteDB already existed, each had different design tradeoffs.
The Comparison
I ran comprehensive benchmarks comparing SoloDB against LiteDB, while trying to make the tests as optimized as possible for both contenders. The results are appended to this document.
The Improvements
In a "GroupBy and count users by username's first letter" query, SoloDB is 57% faster than LiteDB (21,50 ms vs 50,08 ms). But it's not just about raw speed - it's about ease of achieving these speeds.
LiteDB uses its ILiteQueryable interface with a custom query language, while SoloDB takes a different approach with standard IQueryable<T> support.
And the most dramatic improvement was memory allocation. For the same query, LiteDB allocates 30,37 MB while SoloDB uses just 56,05 KB - that's a 99.8% reduction!
These performance improvements are primarily due to SQLite's highly optimized query engine and mature storage architecture that SoloDB builds upon.
The GroupBy Comparison
In a GroupBy query, SoloDB outperforms LiteDB, here is how it is done:
In SoloDB, the test is implemented with LINQ:
var letterCounts = users
.GroupBy(x => x.Username[0])
.Select(x => new { Key = x.Key, Count = x.Count() })
.ToDictionary(k => k.Key.ToString(), e => e.Count);
But in LiteDB it is implemented using their query language(for speed):
var letterCounts = users
.Query()
.GroupBy(BsonExpression.Create("SUBSTRING(Username, 0, 1)"))
.Select(BsonExpression.Create("{key: @key, count: COUNT(*)}"))
.ToEnumerable()
.ToDictionary(k => k["key"].AsString, e => e["count"].AsInt64);
LiteDB's query language offers powerful capabilities, though it requires learning syntax that differs from standard LINQ patterns.
IQueryable Support
SoloDB, by contrast, provides standard IQueryable
support that translates directly to SQL with:
- Full IntelliSense integration
- No need to learn a query language
- Compile-time type safety
- Predictable performance characteristics
- No need for .AsEnumerable() workarounds.
A query like users.Where(x => x.Username.StartsWith("a"))
compiles to SQL, taking advantage of indexes when available, which LiteDB also does.
Here's the SQL SoloDB generates under the hood for that query, it was retrieved by using SoloDB.GetSQL(...)
:
SELECT Id, Value as ValueJSON
FROM (
SELECT Id, jsonb_extract("UserSoloDB".Value, '$') as Value
FROM "UserSoloDB"
WHERE (
-- An index compatible search.
jsonb_extract("UserSoloDB".Value, '$.Username') >= @V171
AND jsonb_extract("UserSoloDB".Value, '$.Username') < @V231
)
)
And its query plan with SoloDB.ExplainQueryPlan(...)
:
SEARCH UserSoloDB USING INDEX UserSoloDB_index_jsonb_extractValueUsername (<expr>>? AND <expr><?)
The Architecture Advantage
SoloDB's foundation takes a different approach by building directly on SQLite's capabilities. This gives us:
- Battle-tested reliability: Used in everything from browsers to spacecraft, SQLite is the most battle-tested database in existence.
- Proper transactions: Full ACID compliance with SQLite's proven transaction system
- Efficient storage: JSONB provides compact storage with fast access
- Compressed Filesystem: The virtual filesystem is transparently compressed using Snappy.
- SQL compatibility: You can use raw SQL when needed.
- Better tooling: Any SQLite tool can inspect your database.
I claim no credit for these features — SoloDB simply stands on the shoulders of the giants behind SQLite.
Different File System Integration
Both databases support file storage, but SoloDB implements a hierarchical virtual filesystem that offers:
- Retrieve entities by Unix-style paths.
- List files and directories using a built-in index.
- Recursively enumerate contents of any folder.
- Write, move, and replace files & directories transactionally.
- Open or copy files by path, as streams or simple read calls.
- Attach and query metadata for richer file context.
- Perform indexed hash-based file lookups.
Performance
By leveraging SQLite's mature architecture, we can obtain the following results:
Operations Where SoloDB Excels
- Inserting 10,000 users:
- SoloDB is 29,3% faster, with 94,9% less memory allocation (622,98 ms -> 440,52 ms)
- Reading random file chunks:
- 41,0% faster, and 68,4% less memory used (14,35 ms -> 8,46 ms)
- Complex queries:
- 95,7% faster, and 99,9% less memory (24,84 ms -> 1,08 ms)
Cases Where LiteDB Has the Edge
Searching within array properties:
LiteDB supports indexes on Properties that are arrays; SoloDB does not — yet.File write operations:
LiteDB is faster when writing files due to its minimal overhead.Very simple queries:
For ultra-fast, cache-resident queries, LiteDB may outperform SoloDB due to smaller query to engine pipeline.
LiteDB excels at file write operations without the overhead of:
- Storing creation and modification timestamps.
- Updating all parent directory timestamps.
- Compressing file chunks with Snappy.
- Hashing contents for integrity and fast lookup.
- Enforcing valid path rules and length limits.
- Preventing illegal names (e.g.,
..
, or malformed paths).
If these features are not required, then LiteDB is better.
The Developer Experience
SoloDB provides a different developer experience:
// SoloDB - intuitive and discoverable
using var db = new SoloDB("./mydb.db");
var users = db.GetCollection<User>();
// Add an index on the count of uploaded files.
users.EnsureIndex(u => u.UploadedFiles.Count);
// Complex queries just work
var gamingFiles = users
.Where(u => u.InterestedCategories.Contains("Gaming")
&& u.UploadedFiles.Count > 5 /* Using the index */)
// Complex projection methods like SelectMany are supported —
// they translate cleanly into SQL when used with simple selectors.
.SelectMany(u => u.UploadedFiles)
.OrderBy(f => f)
.Skip(1)
.Take(10)
.ToList();
// Transactions are simple: commit on return, fail on exception.
db.WithTransaction(tx => {
var users = tx.GetCollection<User>();
// Your transactional operations
});
Just C# that reads like C#.
Advanced Features
Here are some modern features that were not highlighted yet.
- Custom ID generators: Implement your own ID strategy for
Int64
,String
, orGuid
— such as Version 7 GUIDs. - Attribute-based indexing: Use
[Indexed]
attributes for simplicity, or create indexes manually via code. - Hash-based file lookup: All files are SHA-1 content-hashed.
- Auto optimization: On startup, SoloDB runs
PRAGMA optimize;
, enabling SQLite to gather fresh statistics and optimize future queries. - Object inheritance support: Collections support base and derived types.
AnAnimal
collection can store aCat
, and type checks likeanimal.GetType() == typeof(Cat)
are fully supported in queries. - Dapper-like interoperability methods: Execute, Query<T>, QueryFirst<T>, ...
The Verdict
The benchmarks show that SoloDB's approach of building on SQLite's foundation delivers strong performance benefits for many common operations. This is largely thanks to SQLite's decades of optimization work.
Both databases are excellent choices with different architectural philosophies:
SoloDB excels when you need:
- Standard LINQ support without learning new syntax
- SQLite's proven ACID guarantees
- Integration with existing SQLite tooling
- Lower GC memory usage for complex queries
LiteDB remains excellent for:
- Array property indexing (which SoloDB doesn't support yet)
- Faster file write operations
- Simpler deployment scenarios
- Projects already using LiteDB successfully
Ready to choose? Download SoloDB if SQLite's foundation appeals to you, or stick with LiteDB if it's already serving you well.
And if you don't like SoloDB?
Just delete it — and keep using your data directly with SQL.
At the end of the day, all the way down, it's just plain old SQLite.
Data
- LiteDB(5.0.21) vs SoloDB(0.2.2)
- Tested on Win 11 on SSD with CPU AMD Ryzen 9
- .NET 9
- Test iterations: 3
- User count per test: 10_000
- The benchmark project is hosted on GitHub
COMPARISON OF RESULTS
Category: 1.General
|
Category: 2.FS
|
LiteDB DETAILED BENCHMARK RESULTS
Category: 1.General
|
Category: 2.FS
|
SoloDB DETAILED BENCHMARK RESULTS
Category: 1.General
|
Category: 2.FS
|