WitDatabase is a pure .NET library with no native dependencies, enabling it to run on any platform that supports .NET. This includes desktop, server, mobile, and even web browsers via Blazor WebAssembly.


1. Overview

Supported Platforms

WitDatabase runs everywhere .NET runs:

Platform Support Storage Backend Notes
Windows (x64, x86, ARM64) ✅ Full File All features
Linux (x64, ARM64) ✅ Full File All features
macOS (x64, Apple Silicon) ✅ Full File All features
Blazor WebAssembly ✅ Full IndexedDB Browser-based
iOS (via MAUI) ✅ Full File Mobile
Android (via MAUI) ✅ Full File Mobile

.NET Version Requirements

.NET Version Support Notes
.NET 10.0 ✅ Full Recommended
.NET 9.0 ✅ Full Fully supported
.NET 8.0 ⚠️ Untested May work
.NET Framework ❌ No Not supported

Why Pure .NET Matters

Unlike SQLite which requires platform-specific native binaries, WitDatabase is 100% managed code:

[[Svg Src="./witdatabase-deployment-comparison.svg" Alt="witdatabase-deployment-comparison"]]

Platform-Specific Considerations

Platform Encryption Storage Engine Special Package
Windows/Linux/macOS AES-GCM (fast) B+Tree, LSM-Tree None
Blazor WebAssembly ChaCha20 (recommended) B+Tree only OutWit.Database.Core.IndexedDb
iOS/Android AES-GCM or ChaCha20 B+Tree, LSM-Tree None
ARM without AES-NI ChaCha20 (recommended) B+Tree, LSM-Tree OutWit.Database.Core.BouncyCastle

Quick Start by Platform

Desktop/Server (Windows, Linux, macOS):

var db = new WitDatabaseBuilder()
    .WithFilePath("app.witdb")
    .WithBTree()
    .WithTransactions()
    .Build();

Blazor WebAssembly:

var db = new WitDatabaseBuilder()
    .WithIndexedDbStorage("MyApp", JSRuntime)
    .WithBTree()
    .WithBouncyCastleEncryption("password")  // ChaCha20 for WASM
    .Build();
await db.InitializeAsync();

Mobile (MAUI):

var dbPath = Path.Combine(FileSystem.AppDataDirectory, "app.witdb");
var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithEncryption("password")
    .Build();

2. Desktop and Server

Windows

WitDatabase runs on all Windows versions that support .NET 9+:

Windows Version x64 x86 ARM64
Windows 11
Windows 10
Windows Server 2022
Windows Server 2019

Recommended configuration:

// Windows desktop app
var dbPath = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
    "MyApp",
    "data.witdb"
);

var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithEncryption("password")  // AES-GCM, hardware accelerated
    .WithTransactions()
    .Build();

Windows-specific features:

  • AES-NI hardware acceleration (most modern CPUs)
  • NTFS file locking for multi-process safety
  • Full async I/O support

Linux

WitDatabase supports major Linux distributions:

Distribution x64 ARM64
Ubuntu 20.04+
Debian 11+
Fedora 38+
Alpine 3.17+
RHEL/CentOS 8+

Recommended configuration:

// Linux server
var dbPath = "/var/lib/myapp/data.witdb";

var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithEncryption("password")  // AES-GCM on x64
    .WithTransactions()
    .Build();

Linux-specific considerations:

  • File permissions: Ensure app has read/write access to database directory
  • Docker: Mount a volume for data persistence
  • ARM64 (Raspberry Pi, etc.): Consider ChaCha20 if no AES-NI

Docker example:

FROM mcr.microsoft.com/dotnet/aspnet:9.0

WORKDIR /app
COPY --from=build /app/publish .

# Create data directory
RUN mkdir -p /data && chown -R app:app /data
VOLUME /data

ENV DB_PATH=/data/app.witdb

ENTRYPOINT ["dotnet", "MyApp.dll"]
// In app
var dbPath = Environment.GetEnvironmentVariable("DB_PATH") ?? "/data/app.witdb";

macOS

WitDatabase supports both Intel and Apple Silicon Macs:

macOS Version Intel (x64) Apple Silicon (ARM64)
macOS 14+ (Sonoma)
macOS 13 (Ventura)
macOS 12 (Monterey)

Recommended configuration:

// macOS app
var dbPath = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
    "MyApp",
    "data.witdb"
);

var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithEncryption("password")  // AES-GCM on both Intel and M-series
    .WithTransactions()
    .Build();

macOS-specific features:

  • AES hardware acceleration on both Intel and Apple Silicon
  • App Sandbox compatible (use app container for data)
  • Notarization compatible (no native code to sign)

Server Deployment Best Practices

Connection string for production:

"Data Source=/var/lib/myapp/prod.witdb;Encryption=aes-gcm;Password=<from-secrets>;Cache Size=10000;MVCC=true;Isolation Level=Snapshot"

ASP.NET Core configuration:

// Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
{
    var connStr = builder.Configuration.GetConnectionString("WitDb");
    options.UseWitDb(connStr);
});

// appsettings.json
{
  "ConnectionStrings": {
    "WitDb": "Data Source=/data/app.witdb;Encryption=aes-gcm;Password=${DB_PASSWORD}"
  }
}

3. Blazor WebAssembly

WitDatabase can run entirely in the browser using IndexedDB as the storage backend. This enables offline-first web applications with local data persistence.

How It Works

[[Svg Src="./witdatabase-blazor-architecture.svg" Alt="witdatabase-blazor-architecture"]]

Installation

Install the required packages:

<PackageReference Include="OutWit.Database.Core.IndexedDb" Version="1.0.0" />
<PackageReference Include="OutWit.Database.Core.BouncyCastle" Version="1.0.0" />

Add JavaScript files to wwwroot/index.html:

<script src="_content/OutWit.Database.Core.IndexedDb/witdb-indexeddb.js"></script>
<script src="_content/OutWit.Database.Core.IndexedDb/witdb-indexeddb-index.js"></script>

Basic Usage

@page "/data"
@inject IJSRuntime JSRuntime
@using OutWit.Database.Core.Builder
@using OutWit.Database.Core.IndexedDb
@using OutWit.Database.Core.BouncyCastle

@code {
    private WitDatabase? _db;
    
    protected override async Task OnInitializedAsync()
    {
        _db = new WitDatabaseBuilder()
            .WithIndexedDbStorage("MyAppDatabase", JSRuntime)
            .WithBTree()
            .WithTransactions()
            .Build();
        
        // Must initialize async in WASM
        await ((StorageIndexedDb)_db.Store).InitializeAsync();
    }
    
    private async Task SaveData(string key, byte[] value)
    {
        await _db!.PutAsync(Encoding.UTF8.GetBytes(key), value);
    }
    
    private async Task<byte[]?> LoadData(string key)
    {
        return await _db!.GetAsync(Encoding.UTF8.GetBytes(key));
    }
    
    public async ValueTask DisposeAsync()
    {
        if (_db != null)
        {
            await _db.FlushAsync();
            _db.Dispose();
        }
    }
}

With Encryption

Use ChaCha20-Poly1305 for better WASM performance (no AES-NI in browser):

_db = new WitDatabaseBuilder()
    .WithIndexedDbStorage("SecureApp", JSRuntime)
    .WithBTree()
    .WithBouncyCastleEncryptionFast("user", userPassword)  // ChaCha20, fast mode
    .WithTransactions()
    .Build();

Database Service Pattern

Create a reusable service for database access:

// Services/DatabaseService.cs
public class DatabaseService : IAsyncDisposable
{
    private readonly IJSRuntime _jsRuntime;
    private WitDatabase? _db;
    
    public DatabaseService(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }
    
    public async Task InitializeAsync(string? password = null)
    {
        var builder = new WitDatabaseBuilder()
            .WithIndexedDbStorage("MyApp", _jsRuntime)
            .WithBTree()
            .WithTransactions();
        
        if (!string.IsNullOrEmpty(password))
        {
            builder.WithBouncyCastleEncryption(password);
        }
        
        _db = builder.Build();
        await ((StorageIndexedDb)_db.Store).InitializeAsync();
    }
    
    public WitDatabase Database => _db 
        ?? throw new InvalidOperationException("Database not initialized");
    
    public async ValueTask DisposeAsync()
    {
        if (_db != null)
        {
            await _db.FlushAsync();
            _db.Dispose();
        }
    }
}

// Register in Program.cs
builder.Services.AddScoped<DatabaseService>();

Browser Compatibility

Browser Minimum Version IndexedDB Support
Chrome 80+ ✅ Full
Edge 80+ ✅ Full
Firefox 75+ ✅ Full
Safari 14+ ✅ Full

WASM Limitations

Feature Desktop/Server Blazor WASM
B+Tree engine
LSM-Tree engine ❌ (requires file system)
AES-GCM encryption ✅ Fast ⚠️ Slow (no AES-NI)
ChaCha20 encryption ✅ Fast
Transactions
MVCC
Secondary indexes
SQL Engine
Sync I/O ❌ (must use async)

Storage Limits

IndexedDB storage limits vary by browser:

Browser Storage Limit
Chrome 60% of disk space (or ~2GB minimum)
Firefox 50% of disk space
Safari 1GB (may prompt for more)
Edge Same as Chrome

Best practices for WASM:

  • Use ChaCha20 encryption (faster than AES in WASM)
  • Use fast PBKDF2 mode for quicker startup
  • Keep cache size small (300-500 pages)
  • Always use async APIs

4. Mobile (MAUI)

WitDatabase works with .NET MAUI for iOS and Android applications. It uses standard file storage on mobile devices.

Platform Support

Platform Support Storage Location
iOS (iPhone, iPad) ✅ Full App Documents folder
Android ✅ Full App internal storage
Windows (via MAUI) ✅ Full LocalApplicationData
macOS (via MAUI) ✅ Full App container

Installation

<PackageReference Include="OutWit.Database.Core" Version="1.0.0" />
<!-- Or for SQL support -->
<PackageReference Include="OutWit.Database.AdoNet" Version="1.0.0" />
<!-- For ChaCha20 on older ARM devices -->
<PackageReference Include="OutWit.Database.Core.BouncyCastle" Version="1.0.0" />

Basic Usage

// MauiProgram.cs
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });
        
        // Register database service
        builder.Services.AddSingleton<IDatabaseService, DatabaseService>();
        
        return builder.Build();
    }
}
// Services/DatabaseService.cs
public interface IDatabaseService
{
    WitDatabase Database { get; }
    Task InitializeAsync();
}

public class DatabaseService : IDatabaseService, IDisposable
{
    private WitDatabase? _db;
    
    public WitDatabase Database => _db 
        ?? throw new InvalidOperationException("Database not initialized");
    
    public Task InitializeAsync()
    {
        var dbPath = Path.Combine(
            FileSystem.AppDataDirectory,  // Platform-appropriate location
            "app.witdb"
        );
        
        _db = new WitDatabaseBuilder()
            .WithFilePath(dbPath)
            .WithBTree()
            .WithEncryption("your-secure-password")
            .WithTransactions()
            .Build();
        
        return Task.CompletedTask;
    }
    
    public void Dispose()
    {
        _db?.Dispose();
    }
}

Platform-Specific Paths

// FileSystem.AppDataDirectory resolves to:
// iOS:     /var/mobile/Containers/Data/Application/{GUID}/Library/
// Android: /data/data/{package-name}/files/
// Windows: C:\Users\{user}\AppData\Local\{app}\
// macOS:   /Users/{user}/Library/Containers/{bundle-id}/Data/Library/

Encryption on Mobile

iOS and modern Android have hardware AES support:

// AES-GCM (hardware accelerated on modern devices)
var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithEncryption("password")  // AES-GCM
    .Build();

Older ARM devices without AES-NI:

// ChaCha20 (faster on older ARM)
var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithBouncyCastleEncryption("password")  // ChaCha20
    .Build();

Mobile Best Practices

1. Initialize on app start:

// App.xaml.cs
public partial class App : Application
{
    private readonly IDatabaseService _dbService;
    
    public App(IDatabaseService dbService)
    {
        InitializeComponent();
        _dbService = dbService;
        
        MainPage = new AppShell();
    }
    
    protected override async void OnStart()
    {
        await _dbService.InitializeAsync();
    }
}

2. Handle app lifecycle:

// Flush on background/suspend
protected override void OnSleep()
{
    _dbService.Database.Flush();
}

3. Use reasonable cache size:

// Mobile devices have limited memory
var db = new WitDatabaseBuilder()
    .WithFilePath(dbPath)
    .WithBTree()
    .WithCache(cacheSize: 500)  // Conservative for mobile
    .Build();

4. Consider SQLite data protection (iOS):

// iOS Data Protection is automatic for app container files
// WitDatabase encryption adds additional layer

Example: Offline-First Mobile App

public class OfflineRepository<T> where T : class, IEntity
{
    private readonly WitDatabase _db;
    private readonly string _tableName;
    
    public OfflineRepository(WitDatabase db, string tableName)
    {
        _db = db;
        _tableName = tableName;
    }
    
    public async Task SaveAsync(T entity)
    {
        var key = 
Loading...
quot;{_tableName}:{entity.Id}"; var value = JsonSerializer.SerializeToUtf8Bytes(entity); await _db.PutAsync(Encoding.UTF8.GetBytes(key), value); } public async Task<T?> GetAsync(string id) { var key =
Loading...
quot;{_tableName}:{id}"; var value = await _db.GetAsync(Encoding.UTF8.GetBytes(key)); return value != null ? JsonSerializer.Deserialize<T>(value) : null; } public async Task DeleteAsync(string id) { var key =
Loading...
quot;{_tableName}:{id}"; await _db.DeleteAsync(Encoding.UTF8.GetBytes(key)); } }

5. Encryption by Platform

Different platforms have different capabilities for hardware-accelerated encryption. Choosing the right algorithm ensures optimal performance.

Algorithm Selection Guide

[[Svg Src="./witdatabase-encryption-algorithm-decision.svg" Alt="witdatabase-encryption-algorithm-decision"]]

Platform Recommendations

Platform Recommended Algorithm Reason
Windows (x64) AES-GCM AES-NI hardware acceleration
Windows (ARM64) AES-GCM ARMv8 crypto extensions
Linux (x64) AES-GCM AES-NI hardware acceleration
Linux (ARM64) AES-GCM ARMv8 crypto extensions
macOS (Intel) AES-GCM AES-NI hardware acceleration
macOS (Apple Silicon) AES-GCM Hardware acceleration
iOS (iPhone 5s+) AES-GCM ARMv8 crypto extensions
Android (2015+) AES-GCM ARMv8 crypto extensions
Older Android ChaCha20 No AES hardware
Blazor WASM ChaCha20 No hardware acceleration
Raspberry Pi 4 AES-GCM ARMv8 crypto extensions
Raspberry Pi 3 ChaCha20 No AES hardware

Performance Comparison

Encrypting 1000 4KB pages:

Platform AES-GCM ChaCha20
Intel i7 (AES-NI) 15 ms 45 ms
AMD Ryzen (AES-NI) 12 ms 40 ms
Apple M1 10 ms 35 ms
iPhone 14 18 ms 50 ms
Android (Snapdragon 8) 20 ms 55 ms
Raspberry Pi 4 80 ms 100 ms
ARM without AES 120 ms 60 ms
Blazor WASM 800 ms 200 ms

Configuration Examples

Desktop/Server (AES-GCM):

// Built-in, no extra package needed
var db = new WitDatabaseBuilder()
    .WithFilePath("secure.witdb")
    .WithEncryption("password")  // AES-GCM
    .Build();

Blazor WASM (ChaCha20):

// Requires OutWit.Database.Core.BouncyCastle
var db = new WitDatabaseBuilder()
    .WithIndexedDbStorage("SecureApp", JSRuntime)
    .WithBouncyCastleEncryptionFast("user", "password")  // ChaCha20, fast PBKDF2
    .Build();

Cross-platform with runtime detection:

public WitDatabaseBuilder ConfigureEncryption(WitDatabaseBuilder builder, string password)
{
    // Detect if we should use ChaCha20
    bool useChaCha20 = 
        OperatingSystem.IsBrowser() ||  // Blazor WASM
        (OperatingSystem.IsAndroid() && !HasAesNi());  // Older Android
    
    if (useChaCha20)
    {
        return builder.WithBouncyCastleEncryption(password);
    }
    else
    {
        return builder.WithEncryption(password);
    }
}

private bool HasAesNi()
{
    // On Android, check CPU features
    // Most devices from 2015+ have ARMv8 crypto
    return true;  // Simplified; implement actual detection if needed
}

Key Derivation Performance

PBKDF2 iteration count affects startup time:

Mode Iterations Desktop Mobile WASM
Normal 100,000 50 ms 150 ms 2+ sec
Fast 10,000 5 ms 15 ms 200 ms

Use fast mode for WASM:

// Blazor WASM — fast PBKDF2
builder.WithBouncyCastleEncryptionFast("user", "password");

// Or via connection string
"Encryption=chacha20-poly1305;Password=secret;Fast Encryption=true"

6. Quick Reference

Platform Compatibility Matrix

Feature Windows Linux macOS iOS Android WASM
B+Tree
LSM-Tree
AES-GCM ✅ Fast ✅ Fast ✅ Fast ✅ Fast ✅ Fast ⚠️ Slow
ChaCha20 ✅ Fast
Transactions
MVCC
WAL
SQL Engine
ADO.NET
EF Core ⚠️ Limited
Secondary Indexes

Required Packages by Platform

Platform Core IndexedDB BouncyCastle AdoNet EF Core
Desktop/Server ✅ Required Optional Optional Optional
Blazor WASM ✅ Required ✅ Required ✅ Recommended Optional ⚠️ Limited
iOS/Android ✅ Required Optional Optional Optional

Configuration by Platform

Windows/Linux/macOS:

"Data Source=/path/to/app.witdb;Encryption=aes-gcm;Password=secret"

Blazor WASM:

var db = new WitDatabaseBuilder()
    .WithIndexedDbStorage("AppName", JSRuntime)
    .WithBouncyCastleEncryptionFast("user", "password")
    .WithBTree()
    .Build();
await db.InitializeAsync();

MAUI (iOS/Android):

var path = Path.Combine(FileSystem.AppDataDirectory, "app.witdb");
"Data Source=" + path + ";Encryption=aes-gcm;Password=secret"

Storage Locations

Platform Recommended Path
Windows Environment.SpecialFolder.LocalApplicationData
Linux /var/lib/{appname}/ or ~/.local/share/{appname}/
macOS Environment.SpecialFolder.LocalApplicationData
iOS FileSystem.AppDataDirectory
Android FileSystem.AppDataDirectory
WASM IndexedDB (automatic)

Performance Tips by Platform

Desktop/Server:

  • Use large cache (5000-20000 pages)
  • Enable MVCC for concurrent access
  • Use LSM-Tree for write-heavy workloads

Mobile:

  • Use moderate cache (500-1000 pages)
  • Flush on app suspend
  • Consider ChaCha20 on older devices

Blazor WASM:

  • Use small cache (300-500 pages)
  • Use ChaCha20 with fast PBKDF2
  • Always use async APIs
  • B+Tree only (no LSM-Tree)

Troubleshooting

Issue Platform Solution
Slow encryption WASM Switch to ChaCha20
Slow startup WASM Use fast PBKDF2 mode
Storage full WASM Check IndexedDB quota
File access denied Mobile Check app permissions
Database locked All Check file locking settings
Sync I/O hangs WASM Use async APIs only