Migration from V11 to V12

April 19, 2026 · View on GitHub

This guide covers the breaking changes and new features between Akavache V11 and V12.

SQLite backend rewrite

V12 replaces the sqlite-net-pcl ORM with direct SQLitePCLRaw 3.x access. Every SQL statement is prepared once and cached, with parameters bound positionally. This eliminates expression-tree translation overhead and most per-operation allocations on the hot path. Encrypted databases now use SQLite3MultipleCiphers (SQLite3MC) instead of sqlcipher.

No application code changes are required — SqliteBlobCache and EncryptedSqliteBlobCache retain their public API. The on-disk database format is compatible: V12 reads V11 databases directly.

Breaking Changes

Settings use observable-first API

SettingsBase properties are now IObservable<T> backed by SettingsStream<T>. The earlier GetOrCreate<T>/SetOrCreate<T> sync-getter pattern has been removed — it called .Wait() on the underlying observable chain, which deadlocked against the worker-thread SQLite queue.

  public class AppSettings : SettingsBase
  {
      public AppSettings() : base(nameof(AppSettings)) { }

-     public bool Enabled
-     {
-         get => GetOrCreate(true);
-         set => SetOrCreate(value);
-     }
+     public IObservable<bool> Enabled => GetOrCreateObservable(true);
+     public IObservable<Unit> SetEnabled(bool value) => SetObservable(value, nameof(Enabled));
  }

Callers subscribe to Enabled to receive the current value plus any future updates, or call await settings.Enabled.FirstAsync() for a one-shot read.

System.Text.Json package split

Akavache.SystemTextJson has been split into two packages:

  • Akavache.SystemTextJson — Pure System.Text.Json serializer (JSON only, no Newtonsoft dependency). AOT-compatible.
  • Akavache.SystemTextJson.Bson — BSON format support using Newtonsoft.Json.Bson for encoding.

If you were using SystemJsonBsonSerializer or UseSystemJsonBsonSerializer():

- // v11: Single package
- using Akavache.SystemTextJson;
+ // v12: Add reference to Akavache.SystemTextJson.Bson
+ using Akavache.SystemTextJson;       // SystemJsonBsonSerializer lives here (same namespace)
+ using Akavache.SystemTextJson.Bson;  // Builder extensions (UseSystemJsonBsonSerializer)

If you were using only SystemJsonSerializer or WithSerializerSystemTextJson(): no changes needed. The Akavache.SystemTextJson package no longer pulls in Newtonsoft.Json.

SystemJsonBsonSerializer uses composition instead of inheritance

SystemJsonBsonSerializer now implements ISerializer directly and delegates JSON operations to an internal SystemJsonSerializer instance. Code that relied on SystemJsonBsonSerializer is SystemJsonSerializer will need updating.

AOT-safe JsonTypeInfo overloads live in Akavache.SystemTextJson

ISerializer in Akavache.Core stays serializer-agnostic — it does not expose any JsonTypeInfo<T> overloads. The AOT-safe path is provided by extension methods in the Akavache.SystemTextJson namespace:

using Akavache.SystemTextJson;

var bytes  = serializer.Serialize(myModel, AppJsonContext.Default.MyModel);
var result = serializer.Deserialize<MyModel>(bytes, AppJsonContext.Default.MyModel);

New Features

AOT-safe serialization with JsonTypeInfo

SystemJsonSerializer implements JsonTypeInfo<T> overloads for fully AOT-compatible serialization:

[JsonSerializable(typeof(MyModel))]
public partial class AppJsonContext : JsonSerializerContext { }

var serializer = new SystemJsonSerializer();
var bytes = serializer.Serialize(myModel, AppJsonContext.Default.MyModel);
var result = serializer.Deserialize(bytes, AppJsonContext.Default.MyModel);

Universal serializer registry

UniversalSerializer uses an explicit thread-safe registry instead of runtime type discovery. Serializer packages register themselves automatically when configured through builder methods. For manual registration:

UniversalSerializer.RegisterSerializer(() => new SystemJsonSerializer());

V10 to V11 migration shim

The Akavache.V10toV11 package provides a one-time migration path from V10 databases. This is a compatibility-only package — new applications should use Akavache.Sqlite3 directly.