SqliteWasmBlazor 0.9.4-pre

This is a prerelease version of SqliteWasmBlazor.
dotnet add package SqliteWasmBlazor --version 0.9.4-pre
                    
NuGet\Install-Package SqliteWasmBlazor -Version 0.9.4-pre
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SqliteWasmBlazor" Version="0.9.4-pre" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SqliteWasmBlazor" Version="0.9.4-pre" />
                    
Directory.Packages.props
<PackageReference Include="SqliteWasmBlazor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SqliteWasmBlazor --version 0.9.4-pre
                    
#r "nuget: SqliteWasmBlazor, 0.9.4-pre"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SqliteWasmBlazor@0.9.4-pre
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SqliteWasmBlazor&version=0.9.4-pre&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=SqliteWasmBlazor&version=0.9.4-pre&prerelease
                    
Install as a Cake Tool

SqliteWasmBlazor

True filesystem-backed SQLite with full EF Core support for Blazor WebAssembly.

License: MIT .NET NuGet GitHub Repo stars

A real SQLite engine (official sqlite-wasm) runs in a Web Worker on OPFS with synchronous access handles; your app talks to it through a complete ADO.NET provider and EF Core. Data survives refreshes, restarts and browser updates. No server, no emulated filesystem, no manual serialization.

Try the live demo — installable as a PWA for offline use.

Solution Storage Persistence EF Core
InMemory RAM none full
IndexedDB IndexedDB yes limited — no SQL
SQL.js IndexedDB yes none — manual serialization
besql Cache API yes partial — emulated filesystem
SqliteWasmBlazor OPFS yes full

Install

dotnet add package SqliteWasmBlazor --prerelease

Optional at-rest encryption and its drop-in UI are separate packages:

dotnet add package SqliteWasmBlazor.Crypto --prerelease     # encrypted VFS
dotnet add package SqliteWasmBlazor.Crypto.UI --prerelease  # auth / encryption panels

Upgrading from an earlier pre-release? Breaking changes are listed per version in the Changelog.

Quick Start

Program.cs

using SqliteWasmBlazor;

var builder = WebAssemblyHostBuilder.CreateDefault(args);

builder.Services.AddDbContextFactory<TodoDbContext>(options =>
{
    var connection = new SqliteWasmConnection("Data Source=TodoDb.db");
    options.UseSqliteWasm(connection);
});

builder.Services.AddSqliteWasm();

builder.Services.AddSqliteWasmDbContext<TodoDbContext>();

var host = builder.Build();
await host.RunAsync();

Then place the initializer once, in your layout:

<SqliteWasmDatabaseInitializer/>

Program.cs only registers. <SqliteWasmDatabaseInitializer/> renders nothing; after the first render it starts the worker and applies pending migrations for every context declared with AddSqliteWasmDbContext<T>(). A migration that cannot be applied — the schema on disk disagrees with the migrations in the assembly — reports SCHEMA_INCOMPATIBLE with SQLite's reason, and the remedy is a reset: delete the database, ISqliteWasmInitializer.Reset(), InitializeAsync().

The base package reports and never renders — it carries no UI framework. Read IDbInitializationStatus, or register an IDbInitNotifier with AddDbInitNotifier<T>() to be told of MIGRATING, READY and every failure as it happens. SqliteWasmBlazor.Crypto.UI ships <DatabaseInformationAlert/>, which renders those states and offers the reset through the host's IHostRecoveryService.

Initializing after the app renders is what lets a long migration be reported instead of freezing a blank page — and it is the only way an encrypted pool can be opened at all, since its key comes from a WebAuthn ceremony that needs a UI.

Apps deployed on a sub-path must set the base href explicitly:

builder.Services.AddSqliteWasm(o => o.BaseHref =
    new Uri(builder.HostEnvironment.BaseAddress).AbsolutePath);

Use it

@inject IDbContextFactory<TodoDbContext> DbFactory

@code {
    private async Task SaveTodo(TodoItem todo)
    {
        await using var db = await DbFactory.CreateDbContextAsync();
        db.TodoItems.Update(todo);
        await db.SaveChangesAsync(); // persisted to OPFS
    }
}

Your DbContext is an ordinary EF Core context — migrations, LINQ, Include, relationships and decimal arithmetic all work as usual.

Public API

ISqliteWasmDatabaseService (via DI) covers database management outside of EF Core. Every file path streams; none of them holds a database in managed memory.

public interface ISqliteWasmDatabaseService
{
    bool CanCancelQueries { get; }   // a service worker carries cancels to the running statement

    Task<IReadOnlyList<string>> ListDatabasesAsync(CancellationToken ct = default);
    Task<bool> ExistsDatabaseAsync(string databaseName, CancellationToken ct = default);
    Task DeleteDatabaseAsync(string databaseName, CancellationToken ct = default);
    Task RenameDatabaseAsync(string oldName, string newName, CancellationToken ct = default);
    Task CloseDatabaseAsync(string databaseName, CancellationToken ct = default);

    Task ExportDatabaseToStreamAsync(string databaseName, Stream destination,
        CancellationToken ct = default);
    Task ExportDatabaseToDownloadAsync(string databaseName, string filename,
        CancellationToken ct = default);
    Task ExportDatabasesToDownloadAsync(IReadOnlyList<string> databaseNames,
        string filename, CancellationToken ct = default);
    Task ImportDatabaseFromStreamAsync(string databaseName, Stream stream, long size,
        Func<string, CancellationToken, ValueTask>? validateImported = null,
        CancellationToken ct = default);
    Task ImportDatabasesFromStreamAsync(Stream envelopeStream, long envelopeSize,
        Func<string, CancellationToken, ValueTask>? validateImported = null,
        CancellationToken ct = default);

    Task<int> ImportRowsAsync(string databaseName, byte[] data,
        CancellationToken ct = default);
}

Imports park what they replace, run the incoming file past an optional validateImported check, and re-run the host's migrations before the import counts; a refusal restores the previous files byte-identically.

Cancelling a CancellationToken always ends the wait; whether it also stops the running statement depends on a service worker. One importScripts of _content/SqliteWasmBlazor/sqlite-wasm-cancel.sw.js and a call to handleSqliteWasmCancel(event) from its fetch and message listeners is the whole integration; CanCancelQueries says whether a session has it. See Cancelling Queries.

Type Purpose
SqliteWasmConnection / Command / DataReader / Parameter / Transaction ADO.NET provider for direct SQL
IDbInitializationStatus Initialization state and errors
IDbInitNotifier / AddDbInitNotifier<T>() Initialization states pushed to the host as they happen; the host writes the sentences
ISqliteWasmInitializer InitializeAsync() (idempotent) for a page that renders before the layout; Reset() before re-initializing
MessagePackFileHeaderV2 / SchemaHashGenerator Header of an ImportRowsAsync payload and the schema hash it carries
PoolImportResult Outcome of a raw .db import
SchemaMismatchException Thrown by ValidateImportedSchemaAsync; carries MissingTables
PoolOperationRejectedException Typed precondition refusal, carries Reason

Everything else — worker bridge, VFS — is internal.

Optional: at-rest encryption

SqliteWasmBlazor.Crypto adds an encryption layer to the same VFS. Without a registered key it falls through to byte-for-byte vendor SAHPool behavior.

  • Every 4 096-byte page is sealed with ChaCha20-Poly1305, with the AEAD bound to (versionTag, dbPath, slotIndex) so relocated or cross-database pages fail authentication.
  • The key is derived from a passkey via the WebAuthn PRF extension — no password, no key file.
  • Unlock is verified (slot-0 AEAD probe + manifest MAC), not silent.
  • Encrypted whole-pool export (.eds) wraps the key for a recipient X25519 pubkey.
  • SqliteWasmBlazor.Crypto.UI ships drop-in RxBlazorV2 panels (en + de), requires RxBlazorV2.MudBlazor 1.3.2+.
  • Machine-checked: 3 Tamarin theories, 74 lemmas, all verified.

Details: Encrypted VFS · Security · Formal models

Documentation

Topic Description
Architecture Worker-based architecture and technical details
ADO.NET Usage Using the provider without EF Core, transactions
Advanced Features Migrations, FTS5 search, JSON collections, logging, cancelling queries, moving databases in and out
Multi-Database Multiple databases, cross-database references
Bulk Import/Export V2 format, multi-part export, delta sync
Encrypted VFS At-rest encryption and threat model
Recommended Patterns Multi-view pattern, data initialization
FAQ Common questions and browser support
Changelog Release notes, breaking changes, version history

Browser Support

Chrome/Edge 108+, Firefox 111+, Safari 16.4+ — every browser from 2023 on, including iOS/iPadOS Safari and Android Chrome. All support OPFS with synchronous access handles.

Large databases move on mobile. Exports stage through an OPFS file the browser saves from disk; imports stream into the worker one chunk at a time. Neither heap ever holds the whole file, so a multi-hundred-megabyte database transfers on a phone. iOS/iPadOS has the tightest memory budget of the four engines — building for it is what makes the paths safe everywhere.

Installed to the Home Screen there is no downloads folder, so WebKit presents an export on a full-screen OS sheet ("Open in …") instead of saving it. The file streams at any size and the sheet's share menu saves to Files — worth telling your users, since it looks like a failure.

Project Description
RxBlazorV2 Reactive framework for Blazor on R3: source-generated observable models, commands and components.
BlazorPRF WebAuthn-PRF encryption primitives — absorbed into this repo as SqliteWasmBlazor.Crypto.

Together: persistent local storage with optional at-rest encryption, plus reactive state management. Coming next: CryptoSync — end-to-end encrypted multi-device delta sync with per-row permissions and a relay that never sees plaintext.

Project Status

Pre-1.0. The public API is deliberately small and has been stable in practice, but broader real-world feedback is needed before committing to long-term guarantees.

Shipped: ADO.NET provider · OPFS SAHPool · EF Core migrations · FTS5 · multi-database · V2 worker-side bulk import/export · memory-flat streamed export/import · query cancellation · at-rest encryption with passkey-derived keys · drop-in auth/encryption UI · Tamarin-verified crypto lifecycle.

Next: stable NuGet release · CryptoSync (E2E encrypted delta sync) · server-side delta generation.

This is a non-commercial hobby project maintained in spare time — no fixed release cycle. "Hobby" refers to time, not craftsmanship: it is developed with test coverage and attention to code quality. It grows through bug reports, feature requests and pull requests.

Contributing

Issues, bug reports and feature discussions are always welcome. For code we use an issue-first policy: open an issue and agree on the approach before submitting a PR. Trivial fixes can be sent directly. See CONTRIBUTING.md.

Credits

Author: bernisoft · License: MIT (Copyright © 2025 bernisoft), see LICENSE

Built with SQLite / sqlite-wasm, EF Core, MessagePack and MudBlazor.

If you find this useful, please star the repository.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on SqliteWasmBlazor:

Package Downloads
Mythetech.Framework.WebAssembly

WebAssembly-specific components for building blazor applications

BlazorPRF.Persistence

Ready-to-use persistence layer for BlazorPRF applications. Provides trusted contacts, invitations, and settings storage using EF Core with SQLite.

BBH.SqliteWasmBlazor

A Blazor WebAssembly library for SQLite integration in browser history applications

SqliteWasmBlazor.Crypto

Plane 2 engine for SqliteWasmBlazor: PRF-keyed at-rest encryption on top of the plain SQLite engine. Encrypted VFS lifecycle, WebAuthn-PRF key derivation, secure key cache, signing service. Add SqliteWasmBlazor.Crypto.UI for default auth/lock/unlock panels.

SqliteWasmBlazor.Crypto.UI

Base-plane RxBlazorV2 + MudBlazor panels for SqliteWasmBlazor: WebAuthn-PRF authentication / registration, database boot-error alert, session-expired popover. Hosts wire IPrfAuthenticator / ISessionAuthenticator / IDatabaseResetService seams.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.4-pre 130 9/13/2026
0.9.3-pre 829 8/23/2026
0.9.1-pre 890 5/17/2026
0.9.0-pre 632 4/25/2026
0.8.5-pre 852 4/2/2026
0.8.4-pre 111 4/1/2026 0.8.4-pre is deprecated because it has critical bugs.
0.8.3-pre 109 3/31/2026
0.8.1-pre 186 3/27/2026
0.8.0-pre 107 3/18/2026
0.7.2-pre 197 1/28/2026
0.7.1-pre 98 1/27/2026
0.7.0-pre 1,455 11/17/2025
0.6.9-pre 254 11/16/2025
0.6.8-pre 149 11/15/2025
0.6.7-pre 256 11/14/2025
0.6.6-pre 240 11/14/2025
0.6.5-pre 306 11/13/2025
0.6.4-pre 300 11/13/2025
0.6.3-pre 292 11/13/2025
0.6.2-pre 604 11/13/2025
Loading failed

- Full EF Core ADO.NET provider
     - OPFS SAHPool persistence
     - MessagePack binary protocol
     - Complete migration support
     - Custom EF Core decimal functions
     - Dual SQLite instance architecture